VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/DrvMediaISO.cpp@ 6581

Last change on this file since 6581 was 6291, checked in by vboxsync, 17 years ago

Big virtual disk changeset containing several modifications

  • remove the always buggy translation setting and replace it with two sets of geometries, physical and logical
  • complete vmdk creation (fixed/dynamic variants, both split in 2G chunks and single file)
  • implemented VBoxHDD-new generic snapshot support, i.e. diff image creation and image merging (completely untested, I'm pretty sure there are bugs)
  • assorted changes which generalize the VBoxHDD-new interfaces (both externally and internally)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/** @file
2 *
3 * VBox storage devices:
4 * ISO image media driver
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DRV_ISO
23#include <VBox/pdmdrv.h>
24#include <iprt/assert.h>
25#include <iprt/file.h>
26
27#include <string.h>
28
29#include "Builtins.h"
30
31/*******************************************************************************
32* Defined Constants And Macros *
33*******************************************************************************/
34
35/** Converts a pointer to MEDIAISO::IMedia to a PRDVMEDIAISO. */
36#define PDMIMEDIA_2_DRVMEDIAISO(pInterface) ( (PDRVMEDIAISO)((uintptr_t)pInterface - RT_OFFSETOF(DRVMEDIAISO, IMedia)) )
37
38/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
39#define PDMIBASE_2_DRVINS(pInterface) ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
40
41/** Converts a pointer to PDMDRVINS::IBase to a PVBOXHDD. */
42#define PDMIBASE_2_DRVMEDIAISO(pInterface) ( PDMINS2DATA(PDMIBASE_2_DRVINS(pInterface), PDRVMEDIAISO) )
43
44
45
46/*******************************************************************************
47* Structures and Typedefs *
48*******************************************************************************/
49/**
50 * Block driver instance data.
51 */
52typedef struct DRVMEDIAISO
53{
54 /** The media interface. */
55 PDMIMEDIA IMedia;
56 /** Pointer to the driver instance. */
57 PPDMDRVINS pDrvIns;
58 /** Pointer to the filename. (Freed by MM) */
59 char *pszFilename;
60 /** File handle of the ISO file. */
61 RTFILE File;
62} DRVMEDIAISO, *PDRVMEDIAISO;
63
64
65
66/*******************************************************************************
67* Internal Functions *
68*******************************************************************************/
69static DECLCALLBACK(int) drvMediaISORead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead);
70static DECLCALLBACK(int) drvMediaISOWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite);
71static DECLCALLBACK(int) drvMediaISOFlush(PPDMIMEDIA pInterface);
72static DECLCALLBACK(bool) drvMediaISOIsReadOnly(PPDMIMEDIA pInterface);
73static DECLCALLBACK(uint64_t) drvMediaISOGetSize(PPDMIMEDIA pInterface);
74static DECLCALLBACK(int) drvMediaISOGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid);
75static DECLCALLBACK(int) drvMediaISOBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry);
76static DECLCALLBACK(int) drvMediaISOBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry);
77static DECLCALLBACK(int) drvMediaISOBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry);
78static DECLCALLBACK(int) drvMediaISOBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry);
79
80static DECLCALLBACK(void *) drvMediaISOQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface);
81
82
83
84
85/**
86 * Construct a ISO media driver instance.
87 *
88 * @returns VBox status.
89 * @param pDrvIns The driver instance data.
90 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
91 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
92 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
93 * iInstance it's expected to be used a bit in this function.
94 */
95static DECLCALLBACK(int) drvMediaISOConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
96{
97 PDRVMEDIAISO pData = PDMINS2DATA(pDrvIns, PDRVMEDIAISO);
98
99 /*
100 * Init the static parts.
101 */
102 pData->pDrvIns = pDrvIns;
103 pData->File = NIL_RTFILE;
104 /* IBase */
105 pDrvIns->IBase.pfnQueryInterface = drvMediaISOQueryInterface;
106 /* IMedia */
107 pData->IMedia.pfnRead = drvMediaISORead;
108 pData->IMedia.pfnWrite = drvMediaISOWrite;
109 pData->IMedia.pfnFlush = drvMediaISOFlush;
110 pData->IMedia.pfnGetSize = drvMediaISOGetSize;
111 pData->IMedia.pfnGetUuid = drvMediaISOGetUuid;
112 pData->IMedia.pfnIsReadOnly = drvMediaISOIsReadOnly;
113 pData->IMedia.pfnBiosGetPCHSGeometry = drvMediaISOBiosGetPCHSGeometry;
114 pData->IMedia.pfnBiosSetPCHSGeometry = drvMediaISOBiosSetPCHSGeometry;
115 pData->IMedia.pfnBiosGetLCHSGeometry = drvMediaISOBiosGetLCHSGeometry;
116 pData->IMedia.pfnBiosSetLCHSGeometry = drvMediaISOBiosSetLCHSGeometry;
117
118 /*
119 * Read the configuration.
120 */
121 if (!CFGMR3AreValuesValid(pCfgHandle, "Path\0"))
122 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
123
124 char *pszName;
125 int rc = CFGMR3QueryStringAlloc(pCfgHandle, "Path", &pszName);
126 if (VBOX_FAILURE(rc))
127 {
128 AssertMsgFailed(("Configuration error: query for \"Path\" string return %Vra.\n", rc));
129 return rc;
130 }
131
132 /*
133 * Open the image.
134 */
135 rc = RTFileOpen(&pData->File, pszName,
136 RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
137 if (VBOX_SUCCESS(rc))
138 {
139 LogFlow(("drvMediaISOConstruct: ISO image '%s' opened successfully.\n", pszName));
140 pData->pszFilename = pszName;
141 }
142 else
143 {
144 AssertMsgFailed(("Could not open ISO file %s, rc=%Vrc\n", pszName, rc));
145 MMR3HeapFree(pszName);
146 }
147
148 return rc;
149}
150
151
152/**
153 * Destruct a driver instance.
154 *
155 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
156 * resources can be freed correctly.
157 *
158 * @param pDrvIns The driver instance data.
159 */
160static DECLCALLBACK(void) drvMediaISODestruct(PPDMDRVINS pDrvIns)
161{
162 PDRVMEDIAISO pData = PDMINS2DATA(pDrvIns, PDRVMEDIAISO);
163 LogFlow(("drvMediaISODestruct: '%s'\n", pData->pszFilename));
164
165 if (pData->File != NIL_RTFILE)
166 {
167 RTFileClose(pData->File);
168 pData->File = NIL_RTFILE;
169 }
170 if (pData->pszFilename)
171 MMR3HeapFree(pData->pszFilename);
172}
173
174
175/** @copydoc PDMIMEDIA::pfnGetSize */
176static DECLCALLBACK(uint64_t) drvMediaISOGetSize(PPDMIMEDIA pInterface)
177{
178 PDRVMEDIAISO pData = PDMIMEDIA_2_DRVMEDIAISO(pInterface);
179 LogFlow(("drvMediaISOGetSize: '%s'\n", pData->pszFilename));
180
181 uint64_t cbFile;
182 int rc = RTFileGetSize(pData->File, &cbFile);
183 if (VBOX_SUCCESS(rc))
184 {
185 LogFlow(("drvMediaISOGetSize: returns %lld (%s)\n", cbFile, pData->pszFilename));
186 return cbFile;
187 }
188
189 AssertMsgFailed(("Error querying ISO file size, rc=%Vrc. (%s)\n", rc, pData->pszFilename));
190 return 0;
191}
192
193
194/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
195static DECLCALLBACK(int) drvMediaISOBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
196{
197 return VERR_NOT_IMPLEMENTED;
198}
199
200
201/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
202static DECLCALLBACK(int) drvMediaISOBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
203{
204 return VERR_NOT_IMPLEMENTED;
205}
206
207
208/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
209static DECLCALLBACK(int) drvMediaISOBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
210{
211 return VERR_NOT_IMPLEMENTED;
212}
213
214
215/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
216static DECLCALLBACK(int) drvMediaISOBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
217{
218 return VERR_NOT_IMPLEMENTED;
219}
220
221
222/**
223 * Read bits.
224 *
225 * @see PDMIMEDIA::pfnRead for details.
226 */
227static DECLCALLBACK(int) drvMediaISORead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
228{
229 PDRVMEDIAISO pData = PDMIMEDIA_2_DRVMEDIAISO(pInterface);
230 LogFlow(("drvMediaISORead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n", off, pvBuf, cbRead, pData->pszFilename));
231
232 Assert(pData->File);
233 Assert(pvBuf);
234
235 /*
236 * Seek to the position and read.
237 */
238 int rc = RTFileSeek(pData->File, off, RTFILE_SEEK_BEGIN, NULL);
239 if (VBOX_SUCCESS(rc))
240 {
241 rc = RTFileRead(pData->File, pvBuf, cbRead, NULL);
242 if (VBOX_SUCCESS(rc))
243 {
244 Log2(("drvMediaISORead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n"
245 "%16.*Vhxd\n",
246 off, pvBuf, cbRead, pData->pszFilename,
247 cbRead, pvBuf));
248 }
249 else
250 AssertMsgFailed(("RTFileRead(%d, %p, %#x) -> %Vrc (off=%#llx '%s')\n",
251 pData->File, pvBuf, cbRead, rc, off, pData->pszFilename));
252 }
253 else
254 AssertMsgFailed(("RTFileSeek(%d,%#llx,) -> %Vrc\n", pData->File, off, rc));
255 LogFlow(("drvMediaISORead: returns %Vrc\n", rc));
256 return rc;
257}
258
259
260/** @copydoc PDMIMEDIA::pfnWrite */
261static DECLCALLBACK(int) drvMediaISOWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
262{
263 AssertMsgFailed(("Attempt to write to an ISO file!\n"));
264 return VERR_NOT_IMPLEMENTED;
265}
266
267
268/** @copydoc PDMIMEDIA::pfnFlush */
269static DECLCALLBACK(int) drvMediaISOFlush(PPDMIMEDIA pInterface)
270{
271 /* No buffered data that still needs to be written. */
272 return VINF_SUCCESS;
273}
274
275
276/** @copydoc PDMIMEDIA::pfnGetUuid */
277static DECLCALLBACK(int) drvMediaISOGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
278{
279 LogFlow(("drvMediaISOGetUuid: returns VERR_NOT_IMPLEMENTED\n"));
280 return VERR_NOT_IMPLEMENTED;
281}
282
283
284/** @copydoc PDMIMEDIA::pfnIsReadOnly */
285static DECLCALLBACK(bool) drvMediaISOIsReadOnly(PPDMIMEDIA pInterface)
286{
287 return true;
288}
289
290
291/**
292 * Queries an interface to the driver.
293 *
294 * @returns Pointer to interface.
295 * @returns NULL if the interface was not supported by the driver.
296 * @param pInterface Pointer to this interface structure.
297 * @param enmInterface The requested interface identification.
298 * @thread Any thread.
299 */
300static DECLCALLBACK(void *) drvMediaISOQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
301{
302 PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
303 PDRVMEDIAISO pData = PDMINS2DATA(pDrvIns, PDRVMEDIAISO);
304 switch (enmInterface)
305 {
306 case PDMINTERFACE_BASE:
307 return &pDrvIns->IBase;
308 case PDMINTERFACE_MEDIA:
309 return &pData->IMedia;
310 default:
311 return NULL;
312 }
313}
314
315
316/**
317 * ISO media driver registration record.
318 */
319const PDMDRVREG g_DrvMediaISO =
320{
321 /* u32Version */
322 PDM_DRVREG_VERSION,
323 /* szDriverName */
324 "MediaISO",
325 /* pszDescription */
326 "ISO media access driver.",
327 /* fFlags */
328 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
329 /* fClass. */
330 PDM_DRVREG_CLASS_MEDIA,
331 /* cMaxInstances */
332 ~0,
333 /* cbInstance */
334 sizeof(DRVMEDIAISO),
335 /* pfnConstruct */
336 drvMediaISOConstruct,
337 /* pfnDestruct */
338 drvMediaISODestruct,
339 /* pfnIOCtl */
340 NULL,
341 /* pfnPowerOn */
342 NULL,
343 /* pfnReset */
344 NULL,
345 /* pfnSuspend */
346 NULL,
347 /* pfnResume */
348 NULL,
349 /* pfnDetach */
350 NULL,
351 /* pfnPowerOff */
352 NULL
353};
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