VirtualBox

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

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

Storage/RAW: Missing error code to indicate unsupported image formats for non matching extensions. Fixes support for additional image formats through 3rd party plugins

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