VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/DrvRawImage.cpp@ 54153

Last change on this file since 54153 was 45061, checked in by vboxsync, 12 years ago

Review of PDM driver destructors making sure that variables they use are correctly initialized in the constructor. Found several RTFileClose(0) cases.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1/* $Id: DrvRawImage.cpp 45061 2013-03-18 14:09:03Z vboxsync $ */
2/** @file
3 * VBox storage devices: Raw image driver
4 */
5
6/*
7 * Copyright (C) 2006-2012 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_DRV_RAW_IMAGE
23#include <VBox/vmm/pdmdrv.h>
24#include <iprt/assert.h>
25#include <iprt/file.h>
26#include <iprt/string.h>
27#include <iprt/uuid.h>
28
29#include "VBoxDD.h"
30
31
32/*******************************************************************************
33* Structures and Typedefs *
34*******************************************************************************/
35/**
36 * Block driver instance data.
37 *
38 * @implements PDMIMEDIA
39 */
40typedef struct DRVRAWIMAGE
41{
42 /** The media interface. */
43 PDMIMEDIA IMedia;
44 /** Pointer to the driver instance. */
45 PPDMDRVINS pDrvIns;
46 /** Pointer to the filename. (Freed by MM) */
47 char *pszFilename;
48 /** File handle of the raw image file. */
49 RTFILE hFile;
50 /** True if the image is operating in readonly mode. */
51 bool fReadOnly;
52} DRVRAWIMAGE, *PDRVRAWIMAGE;
53
54
55
56/* -=-=-=-=- PDMIMEDIA -=-=-=-=- */
57
58/** @copydoc PDMIMEDIA::pfnGetSize */
59static DECLCALLBACK(uint64_t) drvRawImageGetSize(PPDMIMEDIA pInterface)
60{
61 PDRVRAWIMAGE pThis = RT_FROM_MEMBER(pInterface, DRVRAWIMAGE, IMedia);
62 LogFlow(("drvRawImageGetSize: '%s'\n", pThis->pszFilename));
63
64 uint64_t cbFile;
65 int rc = RTFileGetSize(pThis->hFile, &cbFile);
66 if (RT_SUCCESS(rc))
67 {
68 LogFlow(("drvRawImageGetSize: returns %lld (%s)\n", cbFile, pThis->pszFilename));
69 return cbFile;
70 }
71
72 AssertMsgFailed(("Error querying Raw image file size, rc=%Rrc. (%s)\n", rc, pThis->pszFilename));
73 return 0;
74}
75
76
77/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
78static DECLCALLBACK(int) drvRawImageBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
79{
80 return VERR_NOT_IMPLEMENTED;
81}
82
83
84/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
85static DECLCALLBACK(int) drvRawImageBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
86{
87 return VERR_NOT_IMPLEMENTED;
88}
89
90
91/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
92static DECLCALLBACK(int) drvRawImageBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
93{
94 return VERR_NOT_IMPLEMENTED;
95}
96
97
98/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
99static DECLCALLBACK(int) drvRawImageBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
100{
101 return VERR_NOT_IMPLEMENTED;
102}
103
104
105/**
106 * Read bits.
107 *
108 * @see PDMIMEDIA::pfnRead for details.
109 */
110static DECLCALLBACK(int) drvRawImageRead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
111{
112 PDRVRAWIMAGE pThis = RT_FROM_MEMBER(pInterface, DRVRAWIMAGE, IMedia);
113 LogFlow(("drvRawImageRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n", off, pvBuf, cbRead, pThis->pszFilename));
114
115 Assert(pThis->hFile != NIL_RTFILE);
116 Assert(pvBuf);
117
118 /*
119 * Seek to the position and read.
120 */
121 int rc = RTFileSeek(pThis->hFile, off, RTFILE_SEEK_BEGIN, NULL);
122 if (RT_SUCCESS(rc))
123 {
124 rc = RTFileRead(pThis->hFile, pvBuf, cbRead, NULL);
125 if (RT_SUCCESS(rc))
126 {
127 Log2(("drvRawImageRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n"
128 "%16.*Rhxd\n",
129 off, pvBuf, cbRead, pThis->pszFilename,
130 cbRead, pvBuf));
131 }
132 else
133 AssertMsgFailed(("RTFileRead(%RTfile, %p, %#x) -> %Rrc (off=%#llx '%s')\n",
134 pThis->hFile, pvBuf, cbRead, rc, off, pThis->pszFilename));
135 }
136 else
137 AssertMsgFailed(("RTFileSeek(%RTfile,%#llx,) -> %Rrc\n", pThis->hFile, off, rc));
138 LogFlow(("drvRawImageRead: returns %Rrc\n", rc));
139 return rc;
140}
141
142
143/** @copydoc PDMIMEDIA::pfnWrite */
144static DECLCALLBACK(int) drvRawImageWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
145{
146 PDRVRAWIMAGE pThis = RT_FROM_MEMBER(pInterface, DRVRAWIMAGE, IMedia);
147 LogFlow(("drvRawImageWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n", off, pvBuf, cbWrite, pThis->pszFilename));
148
149 Assert(pThis->hFile != NIL_RTFILE);
150 Assert(pvBuf);
151
152 /*
153 * Seek to the position and write.
154 */
155 int rc = RTFileSeek(pThis->hFile, off, RTFILE_SEEK_BEGIN, NULL);
156 if (RT_SUCCESS(rc))
157 {
158 rc = RTFileWrite(pThis->hFile, pvBuf, cbWrite, NULL);
159 if (RT_SUCCESS(rc))
160 {
161 Log2(("drvRawImageWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n"
162 "%16.*Rhxd\n",
163 off, pvBuf, cbWrite, pThis->pszFilename,
164 cbWrite, pvBuf));
165 }
166 else
167 AssertMsgFailed(("RTFileWrite(%RTfile, %p, %#x) -> %Rrc (off=%#llx '%s')\n",
168 pThis->hFile, pvBuf, cbWrite, rc, off, pThis->pszFilename));
169 }
170 else
171 AssertMsgFailed(("RTFileSeek(%RTfile,%#llx,) -> %Rrc\n", pThis->hFile, off, rc));
172 LogFlow(("drvRawImageWrite: returns %Rrc\n", rc));
173 return rc;
174}
175
176
177/** @copydoc PDMIMEDIA::pfnFlush */
178static DECLCALLBACK(int) drvRawImageFlush(PPDMIMEDIA pInterface)
179{
180 PDRVRAWIMAGE pThis = RT_FROM_MEMBER(pInterface, DRVRAWIMAGE, IMedia);
181 LogFlow(("drvRawImageFlush: (%s)\n", pThis->pszFilename));
182
183 Assert(pThis->hFile != NIL_RTFILE);
184 int rc = RTFileFlush(pThis->hFile);
185 LogFlow(("drvRawImageFlush: returns %Rrc\n", rc));
186 return rc;
187}
188
189
190/** @copydoc PDMIMEDIA::pfnGetUuid */
191static DECLCALLBACK(int) drvRawImageGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
192{
193 LogFlow(("drvRawImageGetUuid: returns VERR_NOT_IMPLEMENTED\n"));
194 return VERR_NOT_IMPLEMENTED;
195}
196
197
198/** @copydoc PDMIMEDIA::pfnIsReadOnly */
199static DECLCALLBACK(bool) drvRawImageIsReadOnly(PPDMIMEDIA pInterface)
200{
201 PDRVRAWIMAGE pThis = RT_FROM_MEMBER(pInterface, DRVRAWIMAGE, IMedia);
202 return pThis->fReadOnly;
203}
204
205
206/* -=-=-=-=- PDMIBASE -=-=-=-=- */
207
208/**
209 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
210 */
211static DECLCALLBACK(void *) drvRawImageQueryInterface(PPDMIBASE pInterface, const char *pszIID)
212{
213 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
214 PDRVRAWIMAGE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWIMAGE);
215
216 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
217 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
218 return NULL;
219}
220
221/* -=-=-=-=- PDMDRVREG -=-=-=-=- */
222
223/**
224 * Destruct a driver instance.
225 *
226 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
227 * resources can be freed correctly.
228 *
229 * @param pDrvIns The driver instance data.
230 */
231static DECLCALLBACK(void) drvRawImageDestruct(PPDMDRVINS pDrvIns)
232{
233 PDRVRAWIMAGE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWIMAGE);
234 LogFlow(("drvRawImageDestruct: '%s'\n", pThis->pszFilename));
235 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
236
237 if (pThis->hFile != NIL_RTFILE)
238 {
239 RTFileClose(pThis->hFile);
240 pThis->hFile = NIL_RTFILE;
241 }
242
243 if (pThis->pszFilename)
244 {
245 MMR3HeapFree(pThis->pszFilename);
246 pThis->pszFilename = NULL;
247 }
248}
249
250
251/**
252 * Construct a raw image driver instance.
253 *
254 * @copydoc FNPDMDRVCONSTRUCT
255 */
256static DECLCALLBACK(int) drvRawImageConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
257{
258 PDRVRAWIMAGE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWIMAGE);
259 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
260
261 /*
262 * Init the static parts.
263 */
264 pThis->pDrvIns = pDrvIns;
265 pThis->hFile = NIL_RTFILE;
266 /* IBase */
267 pDrvIns->IBase.pfnQueryInterface = drvRawImageQueryInterface;
268 /* IMedia */
269 pThis->IMedia.pfnRead = drvRawImageRead;
270 pThis->IMedia.pfnWrite = drvRawImageWrite;
271 pThis->IMedia.pfnFlush = drvRawImageFlush;
272 pThis->IMedia.pfnGetSize = drvRawImageGetSize;
273 pThis->IMedia.pfnGetUuid = drvRawImageGetUuid;
274 pThis->IMedia.pfnIsReadOnly = drvRawImageIsReadOnly;
275 pThis->IMedia.pfnBiosGetPCHSGeometry = drvRawImageBiosGetPCHSGeometry;
276 pThis->IMedia.pfnBiosSetPCHSGeometry = drvRawImageBiosSetPCHSGeometry;
277 pThis->IMedia.pfnBiosGetLCHSGeometry = drvRawImageBiosGetLCHSGeometry;
278 pThis->IMedia.pfnBiosSetLCHSGeometry = drvRawImageBiosSetLCHSGeometry;
279
280 /*
281 * Read the configuration.
282 */
283 if (!CFGMR3AreValuesValid(pCfg, "Path\0"))
284 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
285
286 char *pszName;
287 int rc = CFGMR3QueryStringAlloc(pCfg, "Path", &pszName);
288 if (RT_FAILURE(rc))
289 {
290 AssertMsgFailed(("Configuration error: query for \"Path\" string return %Rrc.\n", rc));
291 return rc;
292 }
293
294 /*
295 * Open the image.
296 */
297 rc = RTFileOpen(&pThis->hFile, pszName, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
298 if (RT_SUCCESS(rc))
299 {
300 LogFlow(("drvRawImageConstruct: Raw image '%s' opened successfully.\n", pszName));
301 pThis->pszFilename = pszName;
302 pThis->fReadOnly = false;
303 }
304 else
305 {
306 rc = RTFileOpen(&pThis->hFile, pszName, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
307 if (RT_SUCCESS(rc))
308 {
309 LogFlow(("drvRawImageConstruct: Raw image '%s' opened successfully.\n", pszName));
310 pThis->pszFilename = pszName;
311 pThis->fReadOnly = true;
312 }
313 else
314 {
315 AssertMsgFailed(("Could not open Raw image file %s, rc=%Rrc\n", pszName, rc));
316 MMR3HeapFree(pszName);
317 }
318 }
319
320 return rc;
321}
322
323
324/**
325 * Raw image driver registration record.
326 */
327const PDMDRVREG g_DrvRawImage =
328{
329 /* u32Version */
330 PDM_DRVREG_VERSION,
331 /* szName */
332 "RawImage",
333 /* szRCMod */
334 "",
335 /* szR0Mod */
336 "",
337 /* pszDescription */
338 "Raw image access driver.",
339 /* fFlags */
340 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
341 /* fClass. */
342 PDM_DRVREG_CLASS_MEDIA,
343 /* cMaxInstances */
344 ~0U,
345 /* cbInstance */
346 sizeof(DRVRAWIMAGE),
347 /* pfnConstruct */
348 drvRawImageConstruct,
349 /* pfnDestruct */
350 drvRawImageDestruct,
351 /* pfnRelocate */
352 NULL,
353 /* pfnIOCtl */
354 NULL,
355 /* pfnPowerOn */
356 NULL,
357 /* pfnReset */
358 NULL,
359 /* pfnSuspend */
360 NULL,
361 /* pfnResume */
362 NULL,
363 /* pfnAttach */
364 NULL,
365 /* pfnDetach */
366 NULL,
367 /* pfnPowerOff */
368 NULL,
369 /* pfnSoftReset */
370 NULL,
371 /* u32EndVersion */
372 PDM_DRVREG_VERSION
373};
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