VirtualBox

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

Last change on this file since 34959 was 33786, checked in by vboxsync, 14 years ago

Storage/RAW: a few more DVD/CD/floppy image extensions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.1 KB
Line 
1/* $Id: RAW.cpp 33786 2010-11-04 17:15:01Z vboxsync $ */
2/** @file
3 * RawHDDCore - Raw Disk image, Core Code.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_VD_RAW
22#include <VBox/vd-plugin.h>
23#include <VBox/err.h>
24
25#include <VBox/log.h>
26#include <iprt/assert.h>
27#include <iprt/alloc.h>
28#include <iprt/path.h>
29
30/*******************************************************************************
31* Constants And Macros, Structures and Typedefs *
32*******************************************************************************/
33
34/**
35 * Raw image data structure.
36 */
37typedef struct RAWIMAGE
38{
39 /** Image name. */
40 const char *pszFilename;
41 /** Storage handle. */
42 PVDIOSTORAGE pStorage;
43 /** I/O interface. */
44 PVDINTERFACE pInterfaceIO;
45 /** Async I/O interface callbacks. */
46 PVDINTERFACEIOINT pInterfaceIOCallbacks;
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
53 /** Error callback. */
54 PVDINTERFACE pInterfaceError;
55 /** Opaque data for error callback. */
56 PVDINTERFACEERROR pInterfaceErrorCallbacks;
57
58 /** Open flags passed by VBoxHD layer. */
59 unsigned uOpenFlags;
60 /** Image flags defined during creation or determined during open. */
61 unsigned uImageFlags;
62 /** Total size of the image. */
63 uint64_t cbSize;
64 /** Position in the image (only truly used for sequential access). */
65 uint64_t offAccess;
66 /** Flag if this is a newly created image. */
67 bool fCreate;
68 /** Physical geometry of this image. */
69 VDGEOMETRY PCHSGeometry;
70 /** Logical geometry of this image. */
71 VDGEOMETRY LCHSGeometry;
72
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. */
80#define RAW_MAX_FLOPPY_IMG_SIZE (512 * 82 * 24 * 2)
81
82/*******************************************************************************
83* Static Variables *
84*******************************************************************************/
85
86/** NULL-terminated array of supported file extensions. */
87static const VDFILEEXTENSION s_aRawFileExtensions[] =
88{
89 {"iso", VDTYPE_DVD},
90 {"cdr", VDTYPE_DVD},
91 {"img", VDTYPE_FLOPPY},
92 {"ima", VDTYPE_FLOPPY},
93 {"dsk", VDTYPE_FLOPPY},
94 {NULL, VDTYPE_INVALID}
95};
96
97/*******************************************************************************
98* Internal Functions *
99*******************************************************************************/
100
101/**
102 * Internal: signal an error to the frontend.
103 */
104DECLINLINE(int) rawError(PRAWIMAGE pImage, int rc, RT_SRC_POS_DECL,
105 const char *pszFormat, ...)
106{
107 va_list va;
108 va_start(va, pszFormat);
109 if (pImage->pInterfaceError)
110 pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,
111 pszFormat, va);
112 va_end(va);
113 return rc;
114}
115
116/**
117 * Internal: signal an informational message to the frontend.
118 */
119DECLINLINE(int) rawMessage(PRAWIMAGE pImage, const char *pszFormat, ...)
120{
121 int rc = VINF_SUCCESS;
122 va_list va;
123 va_start(va, pszFormat);
124 if (pImage->pInterfaceError)
125 rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
126 pszFormat, va);
127 va_end(va);
128 return rc;
129}
130
131
132DECLINLINE(int) rawFileOpen(PRAWIMAGE pImage, const char *pszFilename,
133 uint32_t fOpen)
134{
135 return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
136 pszFilename, fOpen,
137 &pImage->pStorage);
138}
139
140DECLINLINE(int) rawFileClose(PRAWIMAGE pImage)
141{
142 return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
143 pImage->pStorage);
144}
145
146DECLINLINE(int) rawFileDelete(PRAWIMAGE pImage, const char *pszFilename)
147{
148 return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
149 pszFilename);
150}
151
152DECLINLINE(int) rawFileMove(PRAWIMAGE pImage, const char *pszSrc,
153 const char *pszDst, unsigned fMove)
154{
155 return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
156 pszSrc, pszDst, fMove);
157}
158
159DECLINLINE(int) rawFileGetFreeSpace(PRAWIMAGE pImage, const char *pszFilename,
160 int64_t *pcbFree)
161{
162 return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser,
163 pszFilename, pcbFree);
164}
165
166DECLINLINE(int) rawFileGetSize(PRAWIMAGE pImage, uint64_t *pcbSize)
167{
168 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
169 pImage->pStorage, pcbSize);
170}
171
172DECLINLINE(int) rawFileSetSize(PRAWIMAGE pImage, uint64_t cbSize)
173{
174 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
175 pImage->pStorage, cbSize);
176}
177
178DECLINLINE(int) rawFileWriteSync(PRAWIMAGE pImage, uint64_t uOffset,
179 const void *pvBuffer, size_t cbBuffer,
180 size_t *pcbWritten)
181{
182 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
183 pImage->pStorage, uOffset,
184 pvBuffer, cbBuffer, pcbWritten);
185}
186
187DECLINLINE(int) rawFileReadSync(PRAWIMAGE pImage, uint64_t uOffset,
188 void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
189{
190 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
191 pImage->pStorage, uOffset,
192 pvBuffer, cbBuffer, pcbRead);
193}
194
195DECLINLINE(int) rawFileFlushSync(PRAWIMAGE pImage)
196{
197 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
198 pImage->pStorage);
199}
200
201DECLINLINE(int) rawFileReadUserAsync(PRAWIMAGE pImage, uint64_t uOffset,
202 PVDIOCTX pIoCtx, size_t cbRead)
203{
204 return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
205 pImage->pStorage,
206 uOffset, pIoCtx,
207 cbRead);
208}
209
210DECLINLINE(int) rawFileWriteUserAsync(PRAWIMAGE pImage, uint64_t uOffset,
211 PVDIOCTX pIoCtx, size_t cbWrite,
212 PFNVDXFERCOMPLETED pfnComplete,
213 void *pvCompleteUser)
214{
215 return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
216 pImage->pStorage,
217 uOffset, pIoCtx,
218 cbWrite,
219 pfnComplete,
220 pvCompleteUser);
221}
222
223DECLINLINE(int) rawFileFlushAsync(PRAWIMAGE pImage, PVDIOCTX pIoCtx,
224 PFNVDXFERCOMPLETED pfnComplete,
225 void *pvCompleteUser)
226{
227 return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
228 pImage->pStorage,
229 pIoCtx, pfnComplete,
230 pvCompleteUser);
231}
232
233
234/**
235 * Internal. Flush image data to disk.
236 */
237static int rawFlushImage(PRAWIMAGE pImage)
238{
239 int rc = VINF_SUCCESS;
240
241 if ( pImage->pStorage
242 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
243 rc = rawFileFlushSync(pImage);
244
245 return rc;
246}
247
248/**
249 * Internal. Free all allocated space for representing an image except pImage,
250 * and optionally delete the image from disk.
251 */
252static int rawFreeImage(PRAWIMAGE pImage, bool fDelete)
253{
254 int rc = VINF_SUCCESS;
255
256 /* Freeing a never allocated image (e.g. because the open failed) is
257 * not signalled as an error. After all nothing bad happens. */
258 if (pImage)
259 {
260 if (pImage->pStorage)
261 {
262 /* No point updating the file that is deleted anyway. */
263 if (!fDelete)
264 {
265 /* For newly created images in sequential mode fill it to
266 * the nominal size. */
267 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
268 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
269 && pImage->fCreate)
270 {
271 /* Fill rest of image with zeroes, a must for sequential
272 * images to reach the nominal size. */
273 uint64_t uOff;
274 void *pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE);
275 if (!pvBuf)
276 goto out;
277
278 uOff = pImage->offAccess;
279 /* Write data to all image blocks. */
280 while (uOff < pImage->cbSize)
281 {
282 unsigned cbChunk = (unsigned)RT_MIN(pImage->cbSize,
283 RAW_FILL_SIZE);
284
285 rc = rawFileWriteSync(pImage, uOff, pvBuf, cbChunk,
286 NULL);
287 if (RT_FAILURE(rc))
288 goto out;
289
290 uOff += cbChunk;
291 }
292out:
293 if (pvBuf)
294 RTMemTmpFree(pvBuf);
295 }
296 rawFlushImage(pImage);
297 }
298
299 rawFileClose(pImage);
300 pImage->pStorage = NULL;
301 }
302
303 if (fDelete && pImage->pszFilename)
304 rawFileDelete(pImage, pImage->pszFilename);
305 }
306
307 LogFlowFunc(("returns %Rrc\n", rc));
308 return rc;
309}
310
311/**
312 * Internal: Open an image, constructing all necessary data structures.
313 */
314static int rawOpenImage(PRAWIMAGE pImage, unsigned uOpenFlags)
315{
316 int rc;
317
318 pImage->uOpenFlags = uOpenFlags;
319 pImage->fCreate = false;
320
321 pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
322 if (pImage->pInterfaceError)
323 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
324
325 /* Get I/O interface. */
326 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IOINT);
327 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
328 pImage->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pImage->pInterfaceIO);
329 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
330
331 /*
332 * Open the image.
333 */
334 rc = rawFileOpen(pImage, pImage->pszFilename,
335 VDOpenFlagsToFileOpenFlags(uOpenFlags,
336 false /* fCreate */));
337 if (RT_FAILURE(rc))
338 {
339 /* Do NOT signal an appropriate error here, as the VD layer has the
340 * choice of retrying the open if it failed. */
341 goto out;
342 }
343
344 rc = rawFileGetSize(pImage, &pImage->cbSize);
345 if (RT_FAILURE(rc))
346 goto out;
347 if (pImage->cbSize % 512)
348 {
349 rc = VERR_VD_RAW_INVALID_HEADER;
350 goto out;
351 }
352 pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED;
353
354out:
355 if (RT_FAILURE(rc))
356 rawFreeImage(pImage, false);
357 return rc;
358}
359
360/**
361 * Internal: Create a raw image.
362 */
363static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize,
364 unsigned uImageFlags, const char *pszComment,
365 PCVDGEOMETRY pPCHSGeometry,
366 PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags,
367 PFNVDPROGRESS pfnProgress, void *pvUser,
368 unsigned uPercentStart, unsigned uPercentSpan)
369{
370 int rc;
371 RTFOFF cbFree = 0;
372 uint64_t uOff;
373 void *pvBuf = NULL;
374 int32_t fOpen;
375
376 if (uImageFlags & VD_IMAGE_FLAGS_DIFF)
377 {
378 rc = rawError(pImage, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename);
379 goto out;
380 }
381 uImageFlags |= VD_IMAGE_FLAGS_FIXED;
382
383 pImage->uImageFlags = uImageFlags;
384
385 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;
386
387 pImage->uImageFlags = uImageFlags;
388 pImage->fCreate = true;
389 pImage->PCHSGeometry = *pPCHSGeometry;
390 pImage->LCHSGeometry = *pLCHSGeometry;
391
392 pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
393 if (pImage->pInterfaceError)
394 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
395
396 /* Get I/O interface. */
397 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IOINT);
398 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
399 pImage->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pImage->pInterfaceIO);
400 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
401
402 /* Create image file. */
403 fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */);
404 if (uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)
405 fOpen &= ~RTFILE_O_READ;
406 rc = rawFileOpen(pImage, pImage->pszFilename, fOpen);
407 if (RT_FAILURE(rc))
408 {
409 rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename);
410 goto out;
411 }
412
413 if (!(uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
414 {
415 /* Check the free space on the disk and leave early if there is not
416 * sufficient space available. */
417 rc = rawFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree);
418 if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize))
419 {
420 rc = rawError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
421 goto out;
422 }
423
424 /* Allocate & commit whole file if fixed image, it must be more
425 * effective than expanding file by write operations. */
426 rc = rawFileSetSize(pImage, cbSize);
427 if (RT_FAILURE(rc))
428 {
429 rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: setting image size failed for '%s'"), pImage->pszFilename);
430 goto out;
431 }
432
433 /* Fill image with zeroes. We do this for every fixed-size image since
434 * on some systems (for example Windows Vista), it takes ages to write
435 * a block near the end of a sparse file and the guest could complain
436 * about an ATA timeout. */
437 pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE);
438 if (!pvBuf)
439 {
440 rc = VERR_NO_MEMORY;
441 goto out;
442 }
443
444 uOff = 0;
445 /* Write data to all image blocks. */
446 while (uOff < cbSize)
447 {
448 unsigned cbChunk = (unsigned)RT_MIN(cbSize, RAW_FILL_SIZE);
449
450 rc = rawFileWriteSync(pImage, uOff, pvBuf, cbChunk, NULL);
451 if (RT_FAILURE(rc))
452 {
453 rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: writing block failed for '%s'"), pImage->pszFilename);
454 goto out;
455 }
456
457 uOff += cbChunk;
458
459 if (pfnProgress)
460 {
461 rc = pfnProgress(pvUser,
462 uPercentStart + uOff * uPercentSpan * 98 / (cbSize * 100));
463 if (RT_FAILURE(rc))
464 goto out;
465 }
466 }
467 }
468
469 if (RT_SUCCESS(rc) && pfnProgress)
470 pfnProgress(pvUser, uPercentStart + uPercentSpan * 98 / 100);
471
472 pImage->cbSize = cbSize;
473
474 rc = rawFlushImage(pImage);
475
476out:
477 if (pvBuf)
478 RTMemTmpFree(pvBuf);
479
480 if (RT_SUCCESS(rc) && pfnProgress)
481 pfnProgress(pvUser, uPercentStart + uPercentSpan);
482
483 if (RT_FAILURE(rc))
484 rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
485 return rc;
486}
487
488
489/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
490static int rawCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
491 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
492{
493 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
494 PVDIOSTORAGE pStorage = NULL;
495 uint64_t cbFile;
496 int rc = VINF_SUCCESS;
497 char *pszExtension = NULL;
498
499 /* Get I/O interface. */
500 PVDINTERFACE pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IOINT);
501 AssertPtrReturn(pInterfaceIO, VERR_INVALID_PARAMETER);
502 PVDINTERFACEIOINT pInterfaceIOCallbacks = VDGetInterfaceIOInt(pInterfaceIO);
503 AssertPtrReturn(pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
504
505 if ( !VALID_PTR(pszFilename)
506 || !*pszFilename)
507 {
508 rc = VERR_INVALID_PARAMETER;
509 goto out;
510 }
511
512 pszExtension = RTPathExt(pszFilename);
513
514 /*
515 * Open the file and read the footer.
516 */
517 rc = pInterfaceIOCallbacks->pfnOpen(pInterfaceIO->pvUser, pszFilename,
518 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
519 false /* fCreate */),
520 &pStorage);
521 if (RT_SUCCESS(rc))
522 rc = pInterfaceIOCallbacks->pfnGetSize(pInterfaceIO->pvUser, pStorage,
523 &cbFile);
524
525 /* Try to guess the image type based on the extension. */
526 if ( RT_SUCCESS(rc)
527 && pszExtension)
528 {
529 if ( !RTStrICmp(pszExtension, ".iso")
530 || !RTStrICmp(pszExtension, ".cdr")) /* DVD images. */
531 {
532 /* Note that there are ISO images smaller than 1 MB; it is impossible to distinguish
533 * between raw floppy and CD images based on their size (and cannot be reliably done
534 * based on contents, either).
535 */
536 if (cbFile > 32768 && !(cbFile % 2048))
537 {
538 *penmType = VDTYPE_DVD;
539 rc = VINF_SUCCESS;
540 }
541 else
542 rc = VERR_VD_RAW_INVALID_HEADER;
543 }
544 else if ( !RTStrICmp(pszExtension, ".img")
545 || !RTStrICmp(pszExtension, ".ima")
546 || !RTStrICmp(pszExtension, ".dsk")) /* Floppy images */
547 {
548 if (!(cbFile % 512) && cbFile <= RAW_MAX_FLOPPY_IMG_SIZE)
549 {
550 *penmType = VDTYPE_FLOPPY;
551 rc = VINF_SUCCESS;
552 }
553 else
554 rc = VERR_VD_RAW_INVALID_HEADER;
555 }
556 }
557 else
558 rc = VERR_VD_RAW_INVALID_HEADER;
559
560 if (pStorage)
561 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage);
562
563out:
564 LogFlowFunc(("returns %Rrc\n", rc));
565 return rc;
566}
567
568/** @copydoc VBOXHDDBACKEND::pfnOpen */
569static int rawOpen(const char *pszFilename, unsigned uOpenFlags,
570 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
571 VDTYPE enmType, void **ppBackendData)
572{
573 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
574 int rc;
575 PRAWIMAGE pImage;
576
577 /* Check open flags. All valid flags are supported. */
578 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
579 {
580 rc = VERR_INVALID_PARAMETER;
581 goto out;
582 }
583
584 /* Check remaining arguments. */
585 if ( !VALID_PTR(pszFilename)
586 || !*pszFilename)
587 {
588 rc = VERR_INVALID_PARAMETER;
589 goto out;
590 }
591
592
593 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
594 if (!pImage)
595 {
596 rc = VERR_NO_MEMORY;
597 goto out;
598 }
599 pImage->pszFilename = pszFilename;
600 pImage->pStorage = NULL;
601 pImage->pVDIfsDisk = pVDIfsDisk;
602 pImage->pVDIfsImage = pVDIfsImage;
603
604 rc = rawOpenImage(pImage, uOpenFlags);
605 if (RT_SUCCESS(rc))
606 *ppBackendData = pImage;
607 else
608 RTMemFree(pImage);
609
610out:
611 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
612 return rc;
613}
614
615/** @copydoc VBOXHDDBACKEND::pfnCreate */
616static int rawCreate(const char *pszFilename, uint64_t cbSize,
617 unsigned uImageFlags, const char *pszComment,
618 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
619 PCRTUUID pUuid, unsigned uOpenFlags,
620 unsigned uPercentStart, unsigned uPercentSpan,
621 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
622 PVDINTERFACE pVDIfsOperation, void **ppBackendData)
623{
624 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 ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
625 int rc;
626 PRAWIMAGE pImage;
627
628 PFNVDPROGRESS pfnProgress = NULL;
629 void *pvUser = NULL;
630 PVDINTERFACE pIfProgress = VDInterfaceGet(pVDIfsOperation,
631 VDINTERFACETYPE_PROGRESS);
632 PVDINTERFACEPROGRESS pCbProgress = NULL;
633 if (pIfProgress)
634 {
635 pCbProgress = VDGetInterfaceProgress(pIfProgress);
636 if (pCbProgress)
637 pfnProgress = pCbProgress->pfnProgress;
638 pvUser = pIfProgress->pvUser;
639 }
640
641 /* Check open flags. All valid flags are supported. */
642 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
643 {
644 rc = VERR_INVALID_PARAMETER;
645 goto out;
646 }
647
648 /* Check remaining arguments. */
649 if ( !VALID_PTR(pszFilename)
650 || !*pszFilename
651 || !VALID_PTR(pPCHSGeometry)
652 || !VALID_PTR(pLCHSGeometry))
653 {
654 rc = VERR_INVALID_PARAMETER;
655 goto out;
656 }
657
658 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
659 if (!pImage)
660 {
661 rc = VERR_NO_MEMORY;
662 goto out;
663 }
664 pImage->pszFilename = pszFilename;
665 pImage->pStorage = NULL;
666 pImage->pVDIfsDisk = pVDIfsDisk;
667 pImage->pVDIfsImage = pVDIfsImage;
668
669 rc = rawCreateImage(pImage, cbSize, uImageFlags, pszComment,
670 pPCHSGeometry, pLCHSGeometry, uOpenFlags,
671 pfnProgress, pvUser, uPercentStart, uPercentSpan);
672 if (RT_SUCCESS(rc))
673 {
674 /* So far the image is opened in read/write mode. Make sure the
675 * image is opened in read-only mode if the caller requested that. */
676 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
677 {
678 rawFreeImage(pImage, false);
679 rc = rawOpenImage(pImage, uOpenFlags);
680 if (RT_FAILURE(rc))
681 {
682 RTMemFree(pImage);
683 goto out;
684 }
685 }
686 *ppBackendData = pImage;
687 }
688 else
689 RTMemFree(pImage);
690
691out:
692 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
693 return rc;
694}
695
696/** @copydoc VBOXHDDBACKEND::pfnRename */
697static int rawRename(void *pBackendData, const char *pszFilename)
698{
699 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
700 int rc = VINF_SUCCESS;
701 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
702
703 /* Check arguments. */
704 if ( !pImage
705 || !pszFilename
706 || !*pszFilename)
707 {
708 rc = VERR_INVALID_PARAMETER;
709 goto out;
710 }
711
712 /* Close the image. */
713 rc = rawFreeImage(pImage, false);
714 if (RT_FAILURE(rc))
715 goto out;
716
717 /* Rename the file. */
718 rc = rawFileMove(pImage, pImage->pszFilename, pszFilename, 0);
719 if (RT_FAILURE(rc))
720 {
721 /* The move failed, try to reopen the original image. */
722 int rc2 = rawOpenImage(pImage, pImage->uOpenFlags);
723 if (RT_FAILURE(rc2))
724 rc = rc2;
725
726 goto out;
727 }
728
729 /* Update pImage with the new information. */
730 pImage->pszFilename = pszFilename;
731
732 /* Open the old image with new name. */
733 rc = rawOpenImage(pImage, pImage->uOpenFlags);
734 if (RT_FAILURE(rc))
735 goto out;
736
737out:
738 LogFlowFunc(("returns %Rrc\n", rc));
739 return rc;
740}
741
742/** @copydoc VBOXHDDBACKEND::pfnClose */
743static int rawClose(void *pBackendData, bool fDelete)
744{
745 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
746 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
747 int rc;
748
749 rc = rawFreeImage(pImage, fDelete);
750 RTMemFree(pImage);
751
752 LogFlowFunc(("returns %Rrc\n", rc));
753 return rc;
754}
755
756/** @copydoc VBOXHDDBACKEND::pfnRead */
757static int rawRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
758 size_t cbToRead, size_t *pcbActuallyRead)
759{
760 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
761 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
762 int rc;
763
764 AssertPtr(pImage);
765 Assert(uOffset % 512 == 0);
766 Assert(cbToRead % 512 == 0);
767
768 if ( uOffset + cbToRead > pImage->cbSize
769 || cbToRead == 0)
770 {
771 rc = VERR_INVALID_PARAMETER;
772 goto out;
773 }
774
775 /* For sequential access do not allow to go back. */
776 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
777 && uOffset < pImage->offAccess)
778 {
779 rc = VERR_INVALID_PARAMETER;
780 goto out;
781 }
782
783 rc = rawFileReadSync(pImage, uOffset, pvBuf, cbToRead, NULL);
784 pImage->offAccess = uOffset + cbToRead;
785 if (pcbActuallyRead)
786 *pcbActuallyRead = cbToRead;
787
788out:
789 LogFlowFunc(("returns %Rrc\n", rc));
790 return rc;
791}
792
793/** @copydoc VBOXHDDBACKEND::pfnWrite */
794static int rawWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
795 size_t cbToWrite, size_t *pcbWriteProcess,
796 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
797{
798 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
799 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
800 int rc;
801
802 AssertPtr(pImage);
803 Assert(uOffset % 512 == 0);
804 Assert(cbToWrite % 512 == 0);
805
806 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
807 {
808 rc = VERR_VD_IMAGE_READ_ONLY;
809 goto out;
810 }
811
812 if ( uOffset + cbToWrite > pImage->cbSize
813 || cbToWrite == 0)
814 {
815 rc = VERR_INVALID_PARAMETER;
816 goto out;
817 }
818
819 /* For sequential access do not allow to go back. */
820 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
821 && uOffset < pImage->offAccess)
822 {
823 rc = VERR_INVALID_PARAMETER;
824 goto out;
825 }
826
827 rc = rawFileWriteSync(pImage, uOffset, pvBuf, cbToWrite, NULL);
828 pImage->offAccess = uOffset + cbToWrite;
829 if (pcbWriteProcess)
830 *pcbWriteProcess = cbToWrite;
831
832out:
833 LogFlowFunc(("returns %Rrc\n", rc));
834 return rc;
835}
836
837/** @copydoc VBOXHDDBACKEND::pfnFlush */
838static int rawFlush(void *pBackendData)
839{
840 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
841 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
842 int rc;
843
844 rc = rawFlushImage(pImage);
845 LogFlowFunc(("returns %Rrc\n", rc));
846 return rc;
847}
848
849/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
850static unsigned rawGetVersion(void *pBackendData)
851{
852 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
853 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
854
855 AssertPtr(pImage);
856
857 if (pImage)
858 return 1;
859 else
860 return 0;
861}
862
863/** @copydoc VBOXHDDBACKEND::pfnGetSize */
864static uint64_t rawGetSize(void *pBackendData)
865{
866 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
867 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
868 uint64_t cb = 0;
869
870 AssertPtr(pImage);
871
872 if (pImage && pImage->pStorage)
873 cb = pImage->cbSize;
874
875 LogFlowFunc(("returns %llu\n", cb));
876 return cb;
877}
878
879/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
880static uint64_t rawGetFileSize(void *pBackendData)
881{
882 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
883 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
884 uint64_t cb = 0;
885
886 AssertPtr(pImage);
887
888 if (pImage)
889 {
890 uint64_t cbFile;
891 if (pImage->pStorage)
892 {
893 int rc = rawFileGetSize(pImage, &cbFile);
894 if (RT_SUCCESS(rc))
895 cb += cbFile;
896 }
897 }
898
899 LogFlowFunc(("returns %lld\n", cb));
900 return cb;
901}
902
903/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
904static int rawGetPCHSGeometry(void *pBackendData,
905 PVDGEOMETRY pPCHSGeometry)
906{
907 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
908 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
909 int rc;
910
911 AssertPtr(pImage);
912
913 if (pImage)
914 {
915 if (pImage->PCHSGeometry.cCylinders)
916 {
917 *pPCHSGeometry = pImage->PCHSGeometry;
918 rc = VINF_SUCCESS;
919 }
920 else
921 rc = VERR_VD_GEOMETRY_NOT_SET;
922 }
923 else
924 rc = VERR_VD_NOT_OPENED;
925
926 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
927 return rc;
928}
929
930/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
931static int rawSetPCHSGeometry(void *pBackendData,
932 PCVDGEOMETRY pPCHSGeometry)
933{
934 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
935 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
936 int rc;
937
938 AssertPtr(pImage);
939
940 if (pImage)
941 {
942 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
943 {
944 rc = VERR_VD_IMAGE_READ_ONLY;
945 goto out;
946 }
947
948 pImage->PCHSGeometry = *pPCHSGeometry;
949 rc = VINF_SUCCESS;
950 }
951 else
952 rc = VERR_VD_NOT_OPENED;
953
954out:
955 LogFlowFunc(("returns %Rrc\n", rc));
956 return rc;
957}
958
959/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
960static int rawGetLCHSGeometry(void *pBackendData,
961 PVDGEOMETRY pLCHSGeometry)
962{
963 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
964 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
965 int rc;
966
967 AssertPtr(pImage);
968
969 if (pImage)
970 {
971 if (pImage->LCHSGeometry.cCylinders)
972 {
973 *pLCHSGeometry = pImage->LCHSGeometry;
974 rc = VINF_SUCCESS;
975 }
976 else
977 rc = VERR_VD_GEOMETRY_NOT_SET;
978 }
979 else
980 rc = VERR_VD_NOT_OPENED;
981
982 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
983 return rc;
984}
985
986/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
987static int rawSetLCHSGeometry(void *pBackendData,
988 PCVDGEOMETRY pLCHSGeometry)
989{
990 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
991 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
992 int rc;
993
994 AssertPtr(pImage);
995
996 if (pImage)
997 {
998 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
999 {
1000 rc = VERR_VD_IMAGE_READ_ONLY;
1001 goto out;
1002 }
1003
1004 pImage->LCHSGeometry = *pLCHSGeometry;
1005 rc = VINF_SUCCESS;
1006 }
1007 else
1008 rc = VERR_VD_NOT_OPENED;
1009
1010out:
1011 LogFlowFunc(("returns %Rrc\n", rc));
1012 return rc;
1013}
1014
1015/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
1016static unsigned rawGetImageFlags(void *pBackendData)
1017{
1018 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1019 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1020 unsigned uImageFlags;
1021
1022 AssertPtr(pImage);
1023
1024 if (pImage)
1025 uImageFlags = pImage->uImageFlags;
1026 else
1027 uImageFlags = 0;
1028
1029 LogFlowFunc(("returns %#x\n", uImageFlags));
1030 return uImageFlags;
1031}
1032
1033/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
1034static unsigned rawGetOpenFlags(void *pBackendData)
1035{
1036 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1037 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1038 unsigned uOpenFlags;
1039
1040 AssertPtr(pImage);
1041
1042 if (pImage)
1043 uOpenFlags = pImage->uOpenFlags;
1044 else
1045 uOpenFlags = 0;
1046
1047 LogFlowFunc(("returns %#x\n", uOpenFlags));
1048 return uOpenFlags;
1049}
1050
1051/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
1052static int rawSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
1053{
1054 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
1055 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1056 int rc;
1057
1058 /* Image must be opened and the new flags must be valid. */
1059 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
1060 {
1061 rc = VERR_INVALID_PARAMETER;
1062 goto out;
1063 }
1064
1065 /* Implement this operation via reopening the image. */
1066 rc = rawFreeImage(pImage, false);
1067 if (RT_FAILURE(rc))
1068 goto out;
1069 rc = rawOpenImage(pImage, uOpenFlags);
1070
1071out:
1072 LogFlowFunc(("returns %Rrc\n", rc));
1073 return rc;
1074}
1075
1076/** @copydoc VBOXHDDBACKEND::pfnGetComment */
1077static int rawGetComment(void *pBackendData, char *pszComment,
1078 size_t cbComment)
1079{
1080 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
1081 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1082 int rc;
1083
1084 AssertPtr(pImage);
1085
1086 if (pImage)
1087 rc = VERR_NOT_SUPPORTED;
1088 else
1089 rc = VERR_VD_NOT_OPENED;
1090
1091 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
1092 return rc;
1093}
1094
1095/** @copydoc VBOXHDDBACKEND::pfnSetComment */
1096static int rawSetComment(void *pBackendData, const char *pszComment)
1097{
1098 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
1099 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1100 int rc;
1101
1102 AssertPtr(pImage);
1103
1104 if (pImage)
1105 {
1106 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
1107 rc = VERR_VD_IMAGE_READ_ONLY;
1108 else
1109 rc = VERR_NOT_SUPPORTED;
1110 }
1111 else
1112 rc = VERR_VD_NOT_OPENED;
1113
1114 LogFlowFunc(("returns %Rrc\n", rc));
1115 return rc;
1116}
1117
1118/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
1119static int rawGetUuid(void *pBackendData, PRTUUID pUuid)
1120{
1121 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1122 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1123 int rc;
1124
1125 AssertPtr(pImage);
1126
1127 if (pImage)
1128 rc = VERR_NOT_SUPPORTED;
1129 else
1130 rc = VERR_VD_NOT_OPENED;
1131
1132 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1133 return rc;
1134}
1135
1136/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
1137static int rawSetUuid(void *pBackendData, PCRTUUID pUuid)
1138{
1139 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1140 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1141 int rc;
1142
1143 LogFlowFunc(("%RTuuid\n", pUuid));
1144 AssertPtr(pImage);
1145
1146 if (pImage)
1147 {
1148 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1149 rc = VERR_NOT_SUPPORTED;
1150 else
1151 rc = VERR_VD_IMAGE_READ_ONLY;
1152 }
1153 else
1154 rc = VERR_VD_NOT_OPENED;
1155
1156 LogFlowFunc(("returns %Rrc\n", rc));
1157 return rc;
1158}
1159
1160/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
1161static int rawGetModificationUuid(void *pBackendData, PRTUUID pUuid)
1162{
1163 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1164 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1165 int rc;
1166
1167 AssertPtr(pImage);
1168
1169 if (pImage)
1170 rc = VERR_NOT_SUPPORTED;
1171 else
1172 rc = VERR_VD_NOT_OPENED;
1173
1174 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1175 return rc;
1176}
1177
1178/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
1179static int rawSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
1180{
1181 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1182 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1183 int rc;
1184
1185 AssertPtr(pImage);
1186
1187 if (pImage)
1188 {
1189 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1190 rc = VERR_NOT_SUPPORTED;
1191 else
1192 rc = VERR_VD_IMAGE_READ_ONLY;
1193 }
1194 else
1195 rc = VERR_VD_NOT_OPENED;
1196
1197 LogFlowFunc(("returns %Rrc\n", rc));
1198 return rc;
1199}
1200
1201/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
1202static int rawGetParentUuid(void *pBackendData, PRTUUID pUuid)
1203{
1204 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1205 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1206 int rc;
1207
1208 AssertPtr(pImage);
1209
1210 if (pImage)
1211 rc = VERR_NOT_SUPPORTED;
1212 else
1213 rc = VERR_VD_NOT_OPENED;
1214
1215 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1216 return rc;
1217}
1218
1219/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
1220static int rawSetParentUuid(void *pBackendData, PCRTUUID pUuid)
1221{
1222 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1223 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1224 int rc;
1225
1226 AssertPtr(pImage);
1227
1228 if (pImage)
1229 {
1230 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1231 rc = VERR_NOT_SUPPORTED;
1232 else
1233 rc = VERR_VD_IMAGE_READ_ONLY;
1234 }
1235 else
1236 rc = VERR_VD_NOT_OPENED;
1237
1238 LogFlowFunc(("returns %Rrc\n", rc));
1239 return rc;
1240}
1241
1242/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
1243static int rawGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
1244{
1245 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1246 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1247 int rc;
1248
1249 AssertPtr(pImage);
1250
1251 if (pImage)
1252 rc = VERR_NOT_SUPPORTED;
1253 else
1254 rc = VERR_VD_NOT_OPENED;
1255
1256 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1257 return rc;
1258}
1259
1260/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
1261static int rawSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
1262{
1263 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1264 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1265 int rc;
1266
1267 AssertPtr(pImage);
1268
1269 if (pImage)
1270 {
1271 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1272 rc = VERR_NOT_SUPPORTED;
1273 else
1274 rc = VERR_VD_IMAGE_READ_ONLY;
1275 }
1276 else
1277 rc = VERR_VD_NOT_OPENED;
1278
1279 LogFlowFunc(("returns %Rrc\n", rc));
1280 return rc;
1281}
1282
1283/** @copydoc VBOXHDDBACKEND::pfnDump */
1284static void rawDump(void *pBackendData)
1285{
1286 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1287
1288 AssertPtr(pImage);
1289 if (pImage)
1290 {
1291 rawMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
1292 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
1293 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
1294 pImage->cbSize / 512);
1295 }
1296}
1297
1298/** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */
1299static bool rawIsAsyncIOSupported(void *pBackendData)
1300{
1301 return true;
1302}
1303
1304/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
1305static int rawAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
1306 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
1307{
1308 int rc = VINF_SUCCESS;
1309 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1310
1311 rc = rawFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead);
1312 if (RT_SUCCESS(rc))
1313 *pcbActuallyRead = cbRead;
1314
1315 return rc;
1316}
1317
1318/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
1319static int rawAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
1320 PVDIOCTX pIoCtx,
1321 size_t *pcbWriteProcess, size_t *pcbPreRead,
1322 size_t *pcbPostRead, unsigned fWrite)
1323{
1324 int rc = VINF_SUCCESS;
1325 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1326
1327 rc = rawFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL);
1328 if (RT_SUCCESS(rc))
1329 {
1330 *pcbWriteProcess = cbWrite;
1331 *pcbPostRead = 0;
1332 *pcbPreRead = 0;
1333 }
1334
1335 return rc;
1336}
1337
1338/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
1339static int rawAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
1340{
1341 int rc = VINF_SUCCESS;
1342 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1343
1344 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1345 rc = rawFileFlushAsync(pImage, pIoCtx, NULL, NULL);
1346
1347 return rc;
1348}
1349
1350
1351VBOXHDDBACKEND g_RawBackend =
1352{
1353 /* pszBackendName */
1354 "RAW",
1355 /* cbSize */
1356 sizeof(VBOXHDDBACKEND),
1357 /* uBackendCaps */
1358 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
1359 /* paFileExtensions */
1360 s_aRawFileExtensions,
1361 /* paConfigInfo */
1362 NULL,
1363 /* hPlugin */
1364 NIL_RTLDRMOD,
1365 /* pfnCheckIfValid */
1366 rawCheckIfValid,
1367 /* pfnOpen */
1368 rawOpen,
1369 /* pfnCreate */
1370 rawCreate,
1371 /* pfnRename */
1372 rawRename,
1373 /* pfnClose */
1374 rawClose,
1375 /* pfnRead */
1376 rawRead,
1377 /* pfnWrite */
1378 rawWrite,
1379 /* pfnFlush */
1380 rawFlush,
1381 /* pfnGetVersion */
1382 rawGetVersion,
1383 /* pfnGetSize */
1384 rawGetSize,
1385 /* pfnGetFileSize */
1386 rawGetFileSize,
1387 /* pfnGetPCHSGeometry */
1388 rawGetPCHSGeometry,
1389 /* pfnSetPCHSGeometry */
1390 rawSetPCHSGeometry,
1391 /* pfnGetLCHSGeometry */
1392 rawGetLCHSGeometry,
1393 /* pfnSetLCHSGeometry */
1394 rawSetLCHSGeometry,
1395 /* pfnGetImageFlags */
1396 rawGetImageFlags,
1397 /* pfnGetOpenFlags */
1398 rawGetOpenFlags,
1399 /* pfnSetOpenFlags */
1400 rawSetOpenFlags,
1401 /* pfnGetComment */
1402 rawGetComment,
1403 /* pfnSetComment */
1404 rawSetComment,
1405 /* pfnGetUuid */
1406 rawGetUuid,
1407 /* pfnSetUuid */
1408 rawSetUuid,
1409 /* pfnGetModificationUuid */
1410 rawGetModificationUuid,
1411 /* pfnSetModificationUuid */
1412 rawSetModificationUuid,
1413 /* pfnGetParentUuid */
1414 rawGetParentUuid,
1415 /* pfnSetParentUuid */
1416 rawSetParentUuid,
1417 /* pfnGetParentModificationUuid */
1418 rawGetParentModificationUuid,
1419 /* pfnSetParentModificationUuid */
1420 rawSetParentModificationUuid,
1421 /* pfnDump */
1422 rawDump,
1423 /* pfnGetTimeStamp */
1424 NULL,
1425 /* pfnGetParentTimeStamp */
1426 NULL,
1427 /* pfnSetParentTimeStamp */
1428 NULL,
1429 /* pfnGetParentFilename */
1430 NULL,
1431 /* pfnSetParentFilename */
1432 NULL,
1433 /* pfnIsAsyncIOSupported */
1434 rawIsAsyncIOSupported,
1435 /* pfnAsyncRead */
1436 rawAsyncRead,
1437 /* pfnAsyncWrite */
1438 rawAsyncWrite,
1439 /* pfnAsyncFlush */
1440 rawAsyncFlush,
1441 /* pfnComposeLocation */
1442 genericFileComposeLocation,
1443 /* pfnComposeName */
1444 genericFileComposeName,
1445 /* pfnCompact */
1446 NULL,
1447 /* pfnResize */
1448 NULL
1449};
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