VirtualBox

source: vbox/trunk/src/VBox/Devices/Serial/DrvRawFile.cpp@ 94377

Last change on this file since 94377 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/* $Id: DrvRawFile.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VBox stream drivers - Raw file output.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEFAULT
23#include <VBox/vmm/pdmdrv.h>
24#include <iprt/assert.h>
25#include <iprt/file.h>
26#include <iprt/mem.h>
27#include <iprt/poll.h>
28#include <iprt/semaphore.h>
29#include <iprt/stream.h>
30#include <iprt/string.h>
31#include <iprt/uuid.h>
32
33#include "VBoxDD.h"
34
35
36/*********************************************************************************************************************************
37* Defined Constants And Macros *
38*********************************************************************************************************************************/
39
40
41/*********************************************************************************************************************************
42* Structures and Typedefs *
43*********************************************************************************************************************************/
44/**
45 * Raw file output driver instance data.
46 *
47 * @implements PDMISTREAM
48 */
49typedef struct DRVRAWFILE
50{
51 /** The stream interface. */
52 PDMISTREAM IStream;
53 /** Pointer to the driver instance. */
54 PPDMDRVINS pDrvIns;
55 /** Pointer to the file name. (Freed by MM) */
56 char *pszLocation;
57 /** File handle to write the data to. */
58 RTFILE hOutputFile;
59 /** Event semaphore for the poll interface. */
60 RTSEMEVENT hSemEvtPoll;
61} DRVRAWFILE, *PDRVRAWFILE;
62
63
64
65/* -=-=-=-=- PDMISTREAM -=-=-=-=- */
66
67/** @interface_method_impl{PDMISTREAM,pfnPoll} */
68static DECLCALLBACK(int) drvRawFilePoll(PPDMISTREAM pInterface, uint32_t fEvts, uint32_t *pfEvts, RTMSINTERVAL cMillies)
69{
70 PDRVRAWFILE pThis = RT_FROM_MEMBER(pInterface, DRVRAWFILE, IStream);
71
72 Assert(!(fEvts & RTPOLL_EVT_READ)); /* Reading is not supported here. */
73
74 /* Writing is always possible. */
75 if (fEvts & RTPOLL_EVT_WRITE)
76 {
77 *pfEvts = RTPOLL_EVT_WRITE;
78 return VINF_SUCCESS;
79 }
80
81 return RTSemEventWait(pThis->hSemEvtPoll, cMillies);
82}
83
84
85/** @interface_method_impl{PDMISTREAM,pfnPollInterrupt} */
86static DECLCALLBACK(int) drvRawFilePollInterrupt(PPDMISTREAM pInterface)
87{
88 PDRVRAWFILE pThis = RT_FROM_MEMBER(pInterface, DRVRAWFILE, IStream);
89 return RTSemEventSignal(pThis->hSemEvtPoll);
90}
91
92
93/** @interface_method_impl{PDMISTREAM,pfnWrite} */
94static DECLCALLBACK(int) drvRawFileWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
95{
96 int rc = VINF_SUCCESS;
97 PDRVRAWFILE pThis = RT_FROM_MEMBER(pInterface, DRVRAWFILE, IStream);
98 LogFlow(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbWrite, pThis->pszLocation));
99
100 Assert(pvBuf);
101 if (pThis->hOutputFile != NIL_RTFILE)
102 {
103 size_t cbWritten;
104 rc = RTFileWrite(pThis->hOutputFile, pvBuf, *pcbWrite, &cbWritten);
105#if 0
106 /* don't flush here, takes too long and we will loose characters */
107 if (RT_SUCCESS(rc))
108 RTFileFlush(pThis->hOutputFile);
109#endif
110 *pcbWrite = cbWritten;
111 }
112
113 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
114 return rc;
115}
116
117/* -=-=-=-=- PDMIBASE -=-=-=-=- */
118
119/**
120 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
121 */
122static DECLCALLBACK(void *) drvRawFileQueryInterface(PPDMIBASE pInterface, const char *pszIID)
123{
124 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
125 PDRVRAWFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWFILE);
126
127 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
128 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISTREAM, &pThis->IStream);
129 return NULL;
130}
131
132/* -=-=-=-=- PDMDRVREG -=-=-=-=- */
133
134
135/**
136 * Power off a raw output stream driver instance.
137 *
138 * This does most of the destruction work, to avoid ordering dependencies.
139 *
140 * @param pDrvIns The driver instance data.
141 */
142static DECLCALLBACK(void) drvRawFilePowerOff(PPDMDRVINS pDrvIns)
143{
144 PDRVRAWFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWFILE);
145 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
146
147 RTFileClose(pThis->hOutputFile);
148 pThis->hOutputFile = NIL_RTFILE;
149}
150
151
152/**
153 * Destruct a raw output stream driver instance.
154 *
155 * Most VM resources are freed by the VM. This callback is provided so that
156 * any non-VM resources can be freed correctly.
157 *
158 * @param pDrvIns The driver instance data.
159 */
160static DECLCALLBACK(void) drvRawFileDestruct(PPDMDRVINS pDrvIns)
161{
162 PDRVRAWFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWFILE);
163 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
164 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
165
166 if (pThis->pszLocation)
167 PDMDrvHlpMMHeapFree(pDrvIns, pThis->pszLocation);
168
169 if (pThis->hOutputFile != NIL_RTFILE)
170 {
171 RTFileClose(pThis->hOutputFile);
172 pThis->hOutputFile = NIL_RTFILE;
173 }
174
175 if (pThis->hSemEvtPoll != NIL_RTSEMEVENT)
176 {
177 RTSemEventDestroy(pThis->hSemEvtPoll);
178 pThis->hSemEvtPoll = NIL_RTSEMEVENT;
179 }
180}
181
182
183/**
184 * Construct a raw output stream driver instance.
185 *
186 * @copydoc FNPDMDRVCONSTRUCT
187 */
188static DECLCALLBACK(int) drvRawFileConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
189{
190 RT_NOREF(fFlags);
191 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
192 PDRVRAWFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWFILE);
193 PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
194
195 /*
196 * Init the static parts.
197 */
198 pThis->pDrvIns = pDrvIns;
199 pThis->pszLocation = NULL;
200 pThis->hOutputFile = NIL_RTFILE;
201 /* IBase */
202 pDrvIns->IBase.pfnQueryInterface = drvRawFileQueryInterface;
203 /* IStream */
204 pThis->IStream.pfnPoll = drvRawFilePoll;
205 pThis->IStream.pfnPollInterrupt = drvRawFilePollInterrupt;
206 pThis->IStream.pfnRead = NULL;
207 pThis->IStream.pfnWrite = drvRawFileWrite;
208
209 /*
210 * Read the configuration.
211 */
212 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "Location", "");
213
214 int rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "Location", &pThis->pszLocation);
215 if (RT_FAILURE(rc))
216 AssertMsgFailedReturn(("Configuration error: query \"Location\" resulted in %Rrc.\n", rc), rc);
217
218 rc = RTSemEventCreate(&pThis->hSemEvtPoll);
219 AssertRCReturn(rc, rc);
220
221 /*
222 * Open the raw file.
223 */
224 rc = RTFileOpen(&pThis->hOutputFile, pThis->pszLocation, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE);
225 if (RT_FAILURE(rc))
226 {
227 LogRel(("RawFile%d: CreateFile failed rc=%Rrc\n", pDrvIns->iInstance, rc));
228 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("RawFile#%d failed to create the raw output file %s"), pDrvIns->iInstance, pThis->pszLocation);
229 }
230
231 LogFlow(("drvRawFileConstruct: location %s\n", pThis->pszLocation));
232 LogRel(("RawFile#%u: location %s\n", pDrvIns->iInstance, pThis->pszLocation));
233 return VINF_SUCCESS;
234}
235
236
237/**
238 * Raw file driver registration record.
239 */
240const PDMDRVREG g_DrvRawFile =
241{
242 /* u32Version */
243 PDM_DRVREG_VERSION,
244 /* szName */
245 "RawFile",
246 /* szRCMod */
247 "",
248 /* szR0Mod */
249 "",
250 /* pszDescription */
251 "RawFile stream driver.",
252 /* fFlags */
253 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
254 /* fClass. */
255 PDM_DRVREG_CLASS_STREAM,
256 /* cMaxInstances */
257 ~0U,
258 /* cbInstance */
259 sizeof(DRVRAWFILE),
260 /* pfnConstruct */
261 drvRawFileConstruct,
262 /* pfnDestruct */
263 drvRawFileDestruct,
264 /* pfnRelocate */
265 NULL,
266 /* pfnIOCtl */
267 NULL,
268 /* pfnPowerOn */
269 NULL,
270 /* pfnReset */
271 NULL,
272 /* pfnSuspend */
273 NULL,
274 /* pfnResume */
275 NULL,
276 /* pfnAttach */
277 NULL,
278 /* pfnDetach */
279 NULL,
280 /* pfnPowerOff */
281 drvRawFilePowerOff,
282 /* pfnSoftReset */
283 NULL,
284 /* u32EndVersion */
285 PDM_DRVREG_VERSION
286};
287
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette