VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/RawHDDCore.cpp@ 33360

最後變更 在這個檔案從33360是 33234,由 vboxsync 提交於 14 年 前

Storage/RAW: implement sequential read/write case

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette