VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use