VirtualBox

source: vbox/trunk/src/VBox/Storage/RAW.cpp@ 66110

Last change on this file since 66110 was 66110, checked in by vboxsync, 8 years ago

Storage/VD: Implement infrastructure for region lists to be able to support CD/DVD image formats which can contain multiple tracks in the future

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.3 KB
Line 
1/* $Id: RAW.cpp 66110 2017-03-15 12:18:31Z vboxsync $ */
2/** @file
3 * RawHDDCore - Raw Disk image, Core Code.
4 */
5
6/*
7 * Copyright (C) 2006-2016 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_VD_RAW
23#include <VBox/vd-plugin.h>
24#include <VBox/err.h>
25
26#include <VBox/log.h>
27#include <iprt/assert.h>
28#include <iprt/alloc.h>
29#include <iprt/path.h>
30
31#include "VDBackends.h"
32
33
34/*********************************************************************************************************************************
35* Constants And Macros, Structures and Typedefs *
36*********************************************************************************************************************************/
37
38/**
39 * Raw image data structure.
40 */
41typedef struct RAWIMAGE
42{
43 /** Image name. */
44 const char *pszFilename;
45 /** Storage handle. */
46 PVDIOSTORAGE pStorage;
47
48 /** Pointer to the per-disk VD interface list. */
49 PVDINTERFACE pVDIfsDisk;
50 /** Pointer to the per-image VD interface list. */
51 PVDINTERFACE pVDIfsImage;
52 /** Error interface. */
53 PVDINTERFACEERROR pIfError;
54 /** I/O interface. */
55 PVDINTERFACEIOINT pIfIo;
56
57 /** Open flags passed by VBoxHD layer. */
58 unsigned uOpenFlags;
59 /** Image flags defined during creation or determined during open. */
60 unsigned uImageFlags;
61 /** Total size of the image. */
62 uint64_t cbSize;
63 /** Position in the image (only truly used for sequential access). */
64 uint64_t offAccess;
65 /** Flag if this is a newly created image. */
66 bool fCreate;
67 /** Physical geometry of this image. */
68 VDGEOMETRY PCHSGeometry;
69 /** Logical geometry of this image. */
70 VDGEOMETRY LCHSGeometry;
71 /** Sector size of the image. */
72 uint32_t cbSector;
73} RAWIMAGE, *PRAWIMAGE;
74
75
76/** Size of write operations when filling an image with zeroes. */
77#define RAW_FILL_SIZE (128 * _1K)
78
79/** The maximum reasonable size of a floppy image (big format 2.88MB medium). */
80#define RAW_MAX_FLOPPY_IMG_SIZE (512 * 82 * 48 * 2)
81
82
83/*********************************************************************************************************************************
84* Static Variables *
85*********************************************************************************************************************************/
86
87/** NULL-terminated array of supported file extensions. */
88static const VDFILEEXTENSION s_aRawFileExtensions[] =
89{
90 {"iso", VDTYPE_DVD},
91 {"cdr", VDTYPE_DVD},
92 {"img", VDTYPE_FLOPPY},
93 {"ima", VDTYPE_FLOPPY},
94 {"dsk", VDTYPE_FLOPPY},
95 {"flp", VDTYPE_FLOPPY},
96 {"vfd", VDTYPE_FLOPPY},
97 {NULL, VDTYPE_INVALID}
98};
99
100
101/*********************************************************************************************************************************
102* Internal Functions *
103*********************************************************************************************************************************/
104
105/**
106 * Internal. Flush image data to disk.
107 */
108static int rawFlushImage(PRAWIMAGE pImage)
109{
110 int rc = VINF_SUCCESS;
111
112 if ( pImage->pStorage
113 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
114 rc = vdIfIoIntFileFlushSync(pImage->pIfIo, pImage->pStorage);
115
116 return rc;
117}
118
119/**
120 * Internal. Free all allocated space for representing an image except pImage,
121 * and optionally delete the image from disk.
122 */
123static int rawFreeImage(PRAWIMAGE pImage, bool fDelete)
124{
125 int rc = VINF_SUCCESS;
126
127 /* Freeing a never allocated image (e.g. because the open failed) is
128 * not signalled as an error. After all nothing bad happens. */
129 if (pImage)
130 {
131 if (pImage->pStorage)
132 {
133 /* No point updating the file that is deleted anyway. */
134 if (!fDelete)
135 {
136 /* For newly created images in sequential mode fill it to
137 * the nominal size. */
138 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
139 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
140 && pImage->fCreate)
141 {
142 /* Fill rest of image with zeroes, a must for sequential
143 * images to reach the nominal size. */
144 uint64_t uOff;
145 void *pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE);
146 if (RT_LIKELY(pvBuf))
147 {
148 uOff = pImage->offAccess;
149 /* Write data to all image blocks. */
150 while (uOff < pImage->cbSize)
151 {
152 unsigned cbChunk = (unsigned)RT_MIN(pImage->cbSize - uOff,
153 RAW_FILL_SIZE);
154
155 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
156 uOff, pvBuf, cbChunk);
157 if (RT_FAILURE(rc))
158 break;
159
160 uOff += cbChunk;
161 }
162
163 RTMemTmpFree(pvBuf);
164 }
165 else
166 rc = VERR_NO_MEMORY;
167 }
168 rawFlushImage(pImage);
169 }
170
171 rc = vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage);
172 pImage->pStorage = NULL;
173 }
174
175 if (fDelete && pImage->pszFilename)
176 vdIfIoIntFileDelete(pImage->pIfIo, pImage->pszFilename);
177 }
178
179 LogFlowFunc(("returns %Rrc\n", rc));
180 return rc;
181}
182
183/**
184 * Internal: Open an image, constructing all necessary data structures.
185 */
186static int rawOpenImage(PRAWIMAGE pImage, unsigned uOpenFlags)
187{
188 pImage->uOpenFlags = uOpenFlags;
189 pImage->fCreate = false;
190
191 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
192 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
193 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
194
195 /* Open the image. */
196 int rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename,
197 VDOpenFlagsToFileOpenFlags(uOpenFlags,
198 false /* fCreate */),
199 &pImage->pStorage);
200 if (RT_SUCCESS(rc))
201 {
202 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &pImage->cbSize);
203 if ( RT_SUCCESS(rc)
204 && !(pImage->cbSize % 512))
205 pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED;
206 else if (RT_SUCCESS(rc))
207 rc = VERR_VD_RAW_SIZE_MODULO_512;
208 }
209 /* else: Do NOT signal an appropriate error here, as the VD layer has the
210 * choice of retrying the open if it failed. */
211
212 if (RT_FAILURE(rc))
213 rawFreeImage(pImage, false);
214 return rc;
215}
216
217/**
218 * Internal: Create a raw image.
219 */
220static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize,
221 unsigned uImageFlags, const char *pszComment,
222 PCVDGEOMETRY pPCHSGeometry,
223 PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags,
224 PVDINTERFACEPROGRESS pIfProgress,
225 unsigned uPercentStart, unsigned uPercentSpan)
226{
227 RT_NOREF1(pszComment);
228 int rc = VINF_SUCCESS;
229
230 pImage->fCreate = true;
231 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;
232 pImage->uImageFlags = uImageFlags | VD_IMAGE_FLAGS_FIXED;
233 pImage->PCHSGeometry = *pPCHSGeometry;
234 pImage->LCHSGeometry = *pLCHSGeometry;
235 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
236 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
237 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
238
239 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_DIFF))
240 {
241 /* Create image file. */
242 uint32_t fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */);
243 if (uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)
244 fOpen &= ~RTFILE_O_READ;
245 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage);
246 if (RT_SUCCESS(rc))
247 {
248 if (!(uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
249 {
250 RTFOFF cbFree = 0;
251
252 /* Check the free space on the disk and leave early if there is not
253 * sufficient space available. */
254 rc = vdIfIoIntFileGetFreeSpace(pImage->pIfIo, pImage->pszFilename, &cbFree);
255 if (RT_FAILURE(rc) /* ignore errors */ || ((uint64_t)cbFree >= cbSize))
256 {
257 rc = vdIfIoIntFileSetAllocationSize(pImage->pIfIo, pImage->pStorage, cbSize, 0 /* fFlags */,
258 pIfProgress, uPercentStart, uPercentSpan);
259 if (RT_SUCCESS(rc))
260 {
261 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 98 / 100);
262
263 pImage->cbSize = cbSize;
264 rc = rawFlushImage(pImage);
265 }
266 }
267 else
268 rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
269 }
270 else
271 {
272 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbSize);
273 if (RT_SUCCESS(rc))
274 pImage->cbSize = cbSize;
275 }
276 }
277 else
278 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename);
279 }
280 else
281 rc = vdIfError(pImage->pIfError, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename);
282
283 if (RT_SUCCESS(rc))
284 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan);
285
286 if (RT_FAILURE(rc))
287 rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
288 return rc;
289}
290
291
292/** @copydoc VDIMAGEBACKEND::pfnProbe */
293static DECLCALLBACK(int) rawProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
294 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
295{
296 RT_NOREF1(pVDIfsDisk);
297 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
298 PVDIOSTORAGE pStorage = NULL;
299 PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage);
300
301 AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
302 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
303
304 /*
305 * Open the file and read the footer.
306 */
307 int rc = vdIfIoIntFileOpen(pIfIo, pszFilename,
308 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
309 false /* fCreate */),
310 &pStorage);
311 if (RT_SUCCESS(rc))
312 {
313 uint64_t cbFile;
314 const char *pszSuffix = RTPathSuffix(pszFilename);
315 rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile);
316
317 /* Try to guess the image type based on the extension. */
318 if ( RT_SUCCESS(rc)
319 && pszSuffix)
320 {
321 if ( !RTStrICmp(pszSuffix, ".iso")
322 || !RTStrICmp(pszSuffix, ".cdr")) /* DVD images. */
323 {
324 /* Note that there are ISO images smaller than 1 MB; it is impossible to distinguish
325 * between raw floppy and CD images based on their size (and cannot be reliably done
326 * based on contents, either).
327 */
328 if (cbFile % 2048)
329 rc = VERR_VD_RAW_SIZE_MODULO_2048;
330 else if (cbFile <= 32768)
331 rc = VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL;
332 else
333 {
334 *penmType = VDTYPE_DVD;
335 rc = VINF_SUCCESS;
336 }
337 }
338 else if ( !RTStrICmp(pszSuffix, ".img")
339 || !RTStrICmp(pszSuffix, ".ima")
340 || !RTStrICmp(pszSuffix, ".dsk")
341 || !RTStrICmp(pszSuffix, ".flp")
342 || !RTStrICmp(pszSuffix, ".vfd")) /* Floppy images */
343 {
344 if (cbFile % 512)
345 rc = VERR_VD_RAW_SIZE_MODULO_512;
346 else if (cbFile > RAW_MAX_FLOPPY_IMG_SIZE)
347 rc = VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG;
348 else
349 {
350 *penmType = VDTYPE_FLOPPY;
351 rc = VINF_SUCCESS;
352 }
353 }
354 else
355 rc = VERR_VD_RAW_INVALID_HEADER;
356 }
357 else
358 rc = VERR_VD_RAW_INVALID_HEADER;
359 }
360
361 if (pStorage)
362 vdIfIoIntFileClose(pIfIo, pStorage);
363
364 LogFlowFunc(("returns %Rrc\n", rc));
365 return rc;
366}
367
368/** @copydoc VDIMAGEBACKEND::pfnOpen */
369static DECLCALLBACK(int) rawOpen(const char *pszFilename, unsigned uOpenFlags,
370 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
371 VDTYPE enmType, void **ppBackendData)
372{
373 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n",
374 pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData));
375 int rc;
376 PRAWIMAGE pImage;
377
378 NOREF(enmType); /**< @todo r=klaus make use of the type info. */
379
380 /* Check open flags. All valid flags are supported. */
381 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
382 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
383
384 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
385 if (RT_LIKELY(pImage))
386 {
387 pImage->pszFilename = pszFilename;
388 pImage->pStorage = NULL;
389 pImage->pVDIfsDisk = pVDIfsDisk;
390 pImage->pVDIfsImage = pVDIfsImage;
391
392 rc = rawOpenImage(pImage, uOpenFlags);
393 if (RT_SUCCESS(rc))
394 {
395 if (enmType == VDTYPE_DVD)
396 pImage->cbSector = 2048;
397 else
398 pImage->cbSector = 512;
399 *ppBackendData = pImage;
400 }
401 else
402 RTMemFree(pImage);
403 }
404 else
405 rc = VERR_NO_MEMORY;
406
407 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
408 return rc;
409}
410
411/** @copydoc VDIMAGEBACKEND::pfnCreate */
412static DECLCALLBACK(int) rawCreate(const char *pszFilename, uint64_t cbSize,
413 unsigned uImageFlags, const char *pszComment,
414 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
415 PCRTUUID pUuid, unsigned uOpenFlags,
416 unsigned uPercentStart, unsigned uPercentSpan,
417 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
418 PVDINTERFACE pVDIfsOperation, VDTYPE enmType,
419 void **ppBackendData)
420{
421 RT_NOREF1(pUuid);
422 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p enmType=%u ppBackendData=%#p",
423 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, enmType, ppBackendData));
424
425 /* Check the VD container type. Yes, hard disk must be allowed, otherwise
426 * various tools using this backend for hard disk images will fail. */
427 if (enmType != VDTYPE_HDD && enmType != VDTYPE_DVD && enmType != VDTYPE_FLOPPY)
428 return VERR_VD_INVALID_TYPE;
429
430 int rc = VINF_SUCCESS;
431 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);
432
433 /* Check arguments. */
434 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
435 AssertReturn( VALID_PTR(pszFilename)
436 && *pszFilename
437 && VALID_PTR(pPCHSGeometry)
438 && VALID_PTR(pLCHSGeometry), VERR_INVALID_PARAMETER);
439
440 PRAWIMAGE pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
441 if (RT_LIKELY(pImage))
442 {
443 pImage->pszFilename = pszFilename;
444 pImage->pStorage = NULL;
445 pImage->pVDIfsDisk = pVDIfsDisk;
446 pImage->pVDIfsImage = pVDIfsImage;
447
448 rc = rawCreateImage(pImage, cbSize, uImageFlags, pszComment,
449 pPCHSGeometry, pLCHSGeometry, uOpenFlags,
450 pIfProgress, uPercentStart, uPercentSpan);
451 if (RT_SUCCESS(rc))
452 {
453 /* So far the image is opened in read/write mode. Make sure the
454 * image is opened in read-only mode if the caller requested that. */
455 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
456 {
457 rawFreeImage(pImage, false);
458 rc = rawOpenImage(pImage, uOpenFlags);
459 }
460
461 if (RT_SUCCESS(rc))
462 *ppBackendData = pImage;
463 }
464
465 if (RT_FAILURE(rc))
466 RTMemFree(pImage);
467 }
468 else
469 rc = VERR_NO_MEMORY;
470
471 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
472 return rc;
473}
474
475/** @copydoc VDIMAGEBACKEND::pfnRename */
476static DECLCALLBACK(int) rawRename(void *pBackendData, const char *pszFilename)
477{
478 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
479 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
480
481 AssertReturn((pImage && pszFilename && *pszFilename), VERR_INVALID_PARAMETER);
482
483 /* Close the image. */
484 int rc = rawFreeImage(pImage, false);
485 if (RT_SUCCESS(rc))
486 {
487 /* Rename the file. */
488 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0);
489 if (RT_SUCCESS(rc))
490 {
491 /* Update pImage with the new information. */
492 pImage->pszFilename = pszFilename;
493
494 /* Open the old image with new name. */
495 rc = rawOpenImage(pImage, pImage->uOpenFlags);
496 }
497 else
498 {
499 /* The move failed, try to reopen the original image. */
500 int rc2 = rawOpenImage(pImage, pImage->uOpenFlags);
501 if (RT_FAILURE(rc2))
502 rc = rc2;
503 }
504 }
505
506 LogFlowFunc(("returns %Rrc\n", rc));
507 return rc;
508}
509
510/** @copydoc VDIMAGEBACKEND::pfnClose */
511static DECLCALLBACK(int) rawClose(void *pBackendData, bool fDelete)
512{
513 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
514 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
515 int rc = rawFreeImage(pImage, fDelete);
516 RTMemFree(pImage);
517
518 LogFlowFunc(("returns %Rrc\n", rc));
519 return rc;
520}
521
522/** @copydoc VDIMAGEBACKEND::pfnRead */
523static DECLCALLBACK(int) rawRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
524 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
525{
526 int rc = VINF_SUCCESS;
527 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
528
529 /* For sequential access do not allow to go back. */
530 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
531 && uOffset < pImage->offAccess)
532 {
533 *pcbActuallyRead = 0;
534 return VERR_INVALID_PARAMETER;
535 }
536
537 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,
538 pIoCtx, cbToRead);
539 if (RT_SUCCESS(rc))
540 {
541 *pcbActuallyRead = cbToRead;
542 pImage->offAccess = uOffset + cbToRead;
543 }
544
545 return rc;
546}
547
548/** @copydoc VDIMAGEBACKEND::pfnWrite */
549static DECLCALLBACK(int) rawWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
550 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
551 size_t *pcbPostRead, unsigned fWrite)
552{
553 RT_NOREF1(fWrite);
554 int rc = VINF_SUCCESS;
555 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
556
557 /* For sequential access do not allow to go back. */
558 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
559 && uOffset < pImage->offAccess)
560 {
561 *pcbWriteProcess = 0;
562 *pcbPostRead = 0;
563 *pcbPreRead = 0;
564 return VERR_INVALID_PARAMETER;
565 }
566
567 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, uOffset,
568 pIoCtx, cbToWrite, NULL, NULL);
569 if (RT_SUCCESS(rc))
570 {
571 *pcbWriteProcess = cbToWrite;
572 *pcbPostRead = 0;
573 *pcbPreRead = 0;
574 pImage->offAccess = uOffset + cbToWrite;
575 }
576
577 return rc;
578}
579
580/** @copydoc VDIMAGEBACKEND::pfnFlush */
581static DECLCALLBACK(int) rawFlush(void *pBackendData, PVDIOCTX pIoCtx)
582{
583 int rc = VINF_SUCCESS;
584 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
585
586 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
587 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx,
588 NULL, NULL);
589
590 return rc;
591}
592
593/** @copydoc VDIMAGEBACKEND::pfnGetVersion */
594static DECLCALLBACK(unsigned) rawGetVersion(void *pBackendData)
595{
596 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
597 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
598
599 AssertPtrReturn(pImage, 0);
600
601 return 1;
602}
603
604/** @copydoc VDIMAGEBACKEND::pfnGetSize */
605static DECLCALLBACK(uint32_t) rawGetSectorSize(void *pBackendData)
606{
607 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
608 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
609 uint32_t cb = 0;
610
611 AssertPtrReturn(pImage, 0);
612
613 if (pImage->pStorage)
614 cb = pImage->cbSector;
615
616 LogFlowFunc(("returns %u\n", cb));
617 return cb;
618}
619
620/** @copydoc VDIMAGEBACKEND::pfnGetSize */
621static DECLCALLBACK(uint64_t) rawGetSize(void *pBackendData)
622{
623 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
624 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
625 uint64_t cb = 0;
626
627 AssertPtrReturn(pImage, 0);
628
629 if (pImage->pStorage)
630 cb = pImage->cbSize;
631
632 LogFlowFunc(("returns %llu\n", cb));
633 return cb;
634}
635
636/** @copydoc VDIMAGEBACKEND::pfnGetFileSize */
637static DECLCALLBACK(uint64_t) rawGetFileSize(void *pBackendData)
638{
639 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
640 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
641
642 AssertPtrReturn(pImage, 0);
643
644 uint64_t cbFile = 0;
645 if (pImage->pStorage)
646 {
647 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
648 if (RT_FAILURE(rc))
649 cbFile = 0; /* Make sure it is 0 */
650 }
651
652 LogFlowFunc(("returns %lld\n", cbFile));
653 return cbFile;
654}
655
656/** @copydoc VDIMAGEBACKEND::pfnGetPCHSGeometry */
657static DECLCALLBACK(int) rawGetPCHSGeometry(void *pBackendData,
658 PVDGEOMETRY pPCHSGeometry)
659{
660 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
661 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
662 int rc = VINF_SUCCESS;
663
664 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
665
666 if (pImage->PCHSGeometry.cCylinders)
667 *pPCHSGeometry = pImage->PCHSGeometry;
668 else
669 rc = VERR_VD_GEOMETRY_NOT_SET;
670
671 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
672 return rc;
673}
674
675/** @copydoc VDIMAGEBACKEND::pfnSetPCHSGeometry */
676static DECLCALLBACK(int) rawSetPCHSGeometry(void *pBackendData,
677 PCVDGEOMETRY pPCHSGeometry)
678{
679 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n",
680 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
681 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
682 int rc = VINF_SUCCESS;
683
684 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
685
686 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
687 rc = VERR_VD_IMAGE_READ_ONLY;
688 else
689 pImage->PCHSGeometry = *pPCHSGeometry;
690
691 LogFlowFunc(("returns %Rrc\n", rc));
692 return rc;
693}
694
695/** @copydoc VDIMAGEBACKEND::pfnGetLCHSGeometry */
696static DECLCALLBACK(int) rawGetLCHSGeometry(void *pBackendData,
697 PVDGEOMETRY pLCHSGeometry)
698{
699 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
700 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
701 int rc = VINF_SUCCESS;
702
703 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
704
705 if (pImage->LCHSGeometry.cCylinders)
706 *pLCHSGeometry = pImage->LCHSGeometry;
707 else
708 rc = VERR_VD_GEOMETRY_NOT_SET;
709
710 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
711 return rc;
712}
713
714/** @copydoc VDIMAGEBACKEND::pfnSetLCHSGeometry */
715static DECLCALLBACK(int) rawSetLCHSGeometry(void *pBackendData,
716 PCVDGEOMETRY pLCHSGeometry)
717{
718 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n",
719 pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
720 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
721 int rc = VINF_SUCCESS;
722
723 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
724
725 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
726 rc = VERR_VD_IMAGE_READ_ONLY;
727 else
728 pImage->LCHSGeometry = *pLCHSGeometry;
729
730 LogFlowFunc(("returns %Rrc\n", rc));
731 return rc;
732}
733
734/** @copydoc VDIMAGEBACKEND::pfnGetImageFlags */
735static DECLCALLBACK(unsigned) rawGetImageFlags(void *pBackendData)
736{
737 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
738 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
739
740 AssertPtrReturn(pImage, 0);
741
742 LogFlowFunc(("returns %#x\n", pImage->uImageFlags));
743 return pImage->uImageFlags;
744}
745
746/** @copydoc VDIMAGEBACKEND::pfnGetOpenFlags */
747static DECLCALLBACK(unsigned) rawGetOpenFlags(void *pBackendData)
748{
749 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
750 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
751
752 AssertPtrReturn(pImage, 0);
753
754 LogFlowFunc(("returns %#x\n", pImage->uOpenFlags));
755 return pImage->uOpenFlags;
756}
757
758/** @copydoc VDIMAGEBACKEND::pfnSetOpenFlags */
759static DECLCALLBACK(int) rawSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
760{
761 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
762 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
763 int rc = VINF_SUCCESS;
764
765 /* Image must be opened and the new flags must be valid. */
766 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
767 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
768 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
769 rc = VERR_INVALID_PARAMETER;
770 else
771 {
772 /* Implement this operation via reopening the image. */
773 rc = rawFreeImage(pImage, false);
774 if (RT_SUCCESS(rc))
775 rc = rawOpenImage(pImage, uOpenFlags);
776 }
777
778 LogFlowFunc(("returns %Rrc\n", rc));
779 return rc;
780}
781
782/** @copydoc VDIMAGEBACKEND::pfnGetComment */
783static DECLCALLBACK(int) rawGetComment(void *pBackendData, char *pszComment,
784 size_t cbComment)
785{
786 RT_NOREF2(pszComment, cbComment);
787 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
788 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
789
790 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
791
792 LogFlowFunc(("returns %Rrc comment='%s'\n", VERR_NOT_SUPPORTED, pszComment));
793 return VERR_NOT_SUPPORTED;
794}
795
796/** @copydoc VDIMAGEBACKEND::pfnSetComment */
797static DECLCALLBACK(int) rawSetComment(void *pBackendData, const char *pszComment)
798{
799 RT_NOREF1(pszComment);
800 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
801 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
802
803 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
804
805 int rc;
806 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
807 rc = VERR_VD_IMAGE_READ_ONLY;
808 else
809 rc = VERR_NOT_SUPPORTED;
810
811 LogFlowFunc(("returns %Rrc\n", rc));
812 return rc;
813}
814
815/** @copydoc VDIMAGEBACKEND::pfnGetUuid */
816static DECLCALLBACK(int) rawGetUuid(void *pBackendData, PRTUUID pUuid)
817{
818 RT_NOREF1(pUuid);
819 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
820 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
821
822 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
823
824 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
825 return VERR_NOT_SUPPORTED;
826}
827
828/** @copydoc VDIMAGEBACKEND::pfnSetUuid */
829static DECLCALLBACK(int) rawSetUuid(void *pBackendData, PCRTUUID pUuid)
830{
831 RT_NOREF1(pUuid);
832 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
833 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
834
835 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
836
837 int rc;
838 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
839 rc = VERR_VD_IMAGE_READ_ONLY;
840 else
841 rc = VERR_NOT_SUPPORTED;
842
843 LogFlowFunc(("returns %Rrc\n", rc));
844 return rc;
845}
846
847/** @copydoc VDIMAGEBACKEND::pfnGetModificationUuid */
848static DECLCALLBACK(int) rawGetModificationUuid(void *pBackendData, PRTUUID pUuid)
849{
850 RT_NOREF1(pUuid);
851 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
852 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
853
854 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
855
856 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
857 return VERR_NOT_SUPPORTED;
858}
859
860/** @copydoc VDIMAGEBACKEND::pfnSetModificationUuid */
861static DECLCALLBACK(int) rawSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
862{
863 RT_NOREF1(pUuid);
864 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
865 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
866
867 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
868
869 int rc;
870 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
871 rc = VERR_VD_IMAGE_READ_ONLY;
872 else
873 rc = VERR_NOT_SUPPORTED;
874
875 LogFlowFunc(("returns %Rrc\n", rc));
876 return rc;
877}
878
879/** @copydoc VDIMAGEBACKEND::pfnGetParentUuid */
880static DECLCALLBACK(int) rawGetParentUuid(void *pBackendData, PRTUUID pUuid)
881{
882 RT_NOREF1(pUuid);
883 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
884 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
885
886 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
887
888 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
889 return VERR_NOT_SUPPORTED;
890}
891
892/** @copydoc VDIMAGEBACKEND::pfnSetParentUuid */
893static DECLCALLBACK(int) rawSetParentUuid(void *pBackendData, PCRTUUID pUuid)
894{
895 RT_NOREF1(pUuid);
896 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
897 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
898
899 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
900
901 int rc;
902 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
903 rc = VERR_VD_IMAGE_READ_ONLY;
904 else
905 rc = VERR_NOT_SUPPORTED;
906
907 LogFlowFunc(("returns %Rrc\n", rc));
908 return rc;
909}
910
911/** @copydoc VDIMAGEBACKEND::pfnGetParentModificationUuid */
912static DECLCALLBACK(int) rawGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
913{
914 RT_NOREF1(pUuid);
915 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
916 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
917
918 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
919
920 int rc;
921 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
922 rc = VERR_VD_IMAGE_READ_ONLY;
923 else
924 rc = VERR_NOT_SUPPORTED;
925
926 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
927 return rc;
928}
929
930/** @copydoc VDIMAGEBACKEND::pfnSetParentModificationUuid */
931static DECLCALLBACK(int) rawSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
932{
933 RT_NOREF1(pUuid);
934 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
935 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
936
937 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
938
939 int rc;
940 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
941 rc = VERR_VD_IMAGE_READ_ONLY;
942 else
943 rc = VERR_NOT_SUPPORTED;
944
945 LogFlowFunc(("returns %Rrc\n", rc));
946 return rc;
947}
948
949/** @copydoc VDIMAGEBACKEND::pfnDump */
950static DECLCALLBACK(void) rawDump(void *pBackendData)
951{
952 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
953
954 AssertPtrReturnVoid(pImage);
955 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
956 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
957 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
958 pImage->cbSize / 512);
959}
960
961
962
963const VDIMAGEBACKEND g_RawBackend =
964{
965 /* u32Version */
966 VD_IMGBACKEND_VERSION,
967 /* pszBackendName */
968 "RAW",
969 /* uBackendCaps */
970 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
971 /* paFileExtensions */
972 s_aRawFileExtensions,
973 /* paConfigInfo */
974 NULL,
975 /* pfnProbe */
976 rawProbe,
977 /* pfnOpen */
978 rawOpen,
979 /* pfnCreate */
980 rawCreate,
981 /* pfnRename */
982 rawRename,
983 /* pfnClose */
984 rawClose,
985 /* pfnRead */
986 rawRead,
987 /* pfnWrite */
988 rawWrite,
989 /* pfnFlush */
990 rawFlush,
991 /* pfnDiscard */
992 NULL,
993 /* pfnGetVersion */
994 rawGetVersion,
995 /* pfnGetSectorSize */
996 rawGetSectorSize,
997 /* pfnGetSize */
998 rawGetSize,
999 /* pfnGetFileSize */
1000 rawGetFileSize,
1001 /* pfnGetPCHSGeometry */
1002 rawGetPCHSGeometry,
1003 /* pfnSetPCHSGeometry */
1004 rawSetPCHSGeometry,
1005 /* pfnGetLCHSGeometry */
1006 rawGetLCHSGeometry,
1007 /* pfnSetLCHSGeometry */
1008 rawSetLCHSGeometry,
1009 /* pfnQueryRegions */
1010 NULL,
1011 /* pfnRegionListRelease */
1012 NULL,
1013 /* pfnGetImageFlags */
1014 rawGetImageFlags,
1015 /* pfnGetOpenFlags */
1016 rawGetOpenFlags,
1017 /* pfnSetOpenFlags */
1018 rawSetOpenFlags,
1019 /* pfnGetComment */
1020 rawGetComment,
1021 /* pfnSetComment */
1022 rawSetComment,
1023 /* pfnGetUuid */
1024 rawGetUuid,
1025 /* pfnSetUuid */
1026 rawSetUuid,
1027 /* pfnGetModificationUuid */
1028 rawGetModificationUuid,
1029 /* pfnSetModificationUuid */
1030 rawSetModificationUuid,
1031 /* pfnGetParentUuid */
1032 rawGetParentUuid,
1033 /* pfnSetParentUuid */
1034 rawSetParentUuid,
1035 /* pfnGetParentModificationUuid */
1036 rawGetParentModificationUuid,
1037 /* pfnSetParentModificationUuid */
1038 rawSetParentModificationUuid,
1039 /* pfnDump */
1040 rawDump,
1041 /* pfnGetTimestamp */
1042 NULL,
1043 /* pfnGetParentTimestamp */
1044 NULL,
1045 /* pfnSetParentTimestamp */
1046 NULL,
1047 /* pfnGetParentFilename */
1048 NULL,
1049 /* pfnSetParentFilename */
1050 NULL,
1051 /* pfnComposeLocation */
1052 genericFileComposeLocation,
1053 /* pfnComposeName */
1054 genericFileComposeName,
1055 /* pfnCompact */
1056 NULL,
1057 /* pfnResize */
1058 NULL,
1059 /* pfnRepair */
1060 NULL,
1061 /* pfnTraverseMetadata */
1062 NULL,
1063 /* u32VersionEnd */
1064 VD_IMGBACKEND_VERSION
1065};
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