VirtualBox

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

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

Storage/RAW: waste of time

  • 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 35045 2010-12-13 21:14: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 }
559 else
560 rc = VERR_VD_RAW_INVALID_HEADER;
561
562 if (pStorage)
563 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage);
564
565out:
566 LogFlowFunc(("returns %Rrc\n", rc));
567 return rc;
568}
569
570/** @copydoc VBOXHDDBACKEND::pfnOpen */
571static int rawOpen(const char *pszFilename, unsigned uOpenFlags,
572 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
573 VDTYPE enmType, void **ppBackendData)
574{
575 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
576 int rc;
577 PRAWIMAGE pImage;
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 {
590 rc = VERR_INVALID_PARAMETER;
591 goto out;
592 }
593
594
595 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
596 if (!pImage)
597 {
598 rc = VERR_NO_MEMORY;
599 goto out;
600 }
601 pImage->pszFilename = pszFilename;
602 pImage->pStorage = NULL;
603 pImage->pVDIfsDisk = pVDIfsDisk;
604 pImage->pVDIfsImage = pVDIfsImage;
605
606 rc = rawOpenImage(pImage, uOpenFlags);
607 if (RT_SUCCESS(rc))
608 *ppBackendData = pImage;
609 else
610 RTMemFree(pImage);
611
612out:
613 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
614 return rc;
615}
616
617/** @copydoc VBOXHDDBACKEND::pfnCreate */
618static int rawCreate(const char *pszFilename, uint64_t cbSize,
619 unsigned uImageFlags, const char *pszComment,
620 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
621 PCRTUUID pUuid, unsigned uOpenFlags,
622 unsigned uPercentStart, unsigned uPercentSpan,
623 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
624 PVDINTERFACE pVDIfsOperation, void **ppBackendData)
625{
626 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));
627 int rc;
628 PRAWIMAGE pImage;
629
630 PFNVDPROGRESS pfnProgress = NULL;
631 void *pvUser = NULL;
632 PVDINTERFACE pIfProgress = VDInterfaceGet(pVDIfsOperation,
633 VDINTERFACETYPE_PROGRESS);
634 PVDINTERFACEPROGRESS pCbProgress = NULL;
635 if (pIfProgress)
636 {
637 pCbProgress = VDGetInterfaceProgress(pIfProgress);
638 if (pCbProgress)
639 pfnProgress = pCbProgress->pfnProgress;
640 pvUser = pIfProgress->pvUser;
641 }
642
643 /* Check open flags. All valid flags are supported. */
644 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
645 {
646 rc = VERR_INVALID_PARAMETER;
647 goto out;
648 }
649
650 /* Check remaining arguments. */
651 if ( !VALID_PTR(pszFilename)
652 || !*pszFilename
653 || !VALID_PTR(pPCHSGeometry)
654 || !VALID_PTR(pLCHSGeometry))
655 {
656 rc = VERR_INVALID_PARAMETER;
657 goto out;
658 }
659
660 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
661 if (!pImage)
662 {
663 rc = VERR_NO_MEMORY;
664 goto out;
665 }
666 pImage->pszFilename = pszFilename;
667 pImage->pStorage = NULL;
668 pImage->pVDIfsDisk = pVDIfsDisk;
669 pImage->pVDIfsImage = pVDIfsImage;
670
671 rc = rawCreateImage(pImage, cbSize, uImageFlags, pszComment,
672 pPCHSGeometry, pLCHSGeometry, uOpenFlags,
673 pfnProgress, pvUser, uPercentStart, uPercentSpan);
674 if (RT_SUCCESS(rc))
675 {
676 /* So far the image is opened in read/write mode. Make sure the
677 * image is opened in read-only mode if the caller requested that. */
678 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
679 {
680 rawFreeImage(pImage, false);
681 rc = rawOpenImage(pImage, uOpenFlags);
682 if (RT_FAILURE(rc))
683 {
684 RTMemFree(pImage);
685 goto out;
686 }
687 }
688 *ppBackendData = pImage;
689 }
690 else
691 RTMemFree(pImage);
692
693out:
694 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
695 return rc;
696}
697
698/** @copydoc VBOXHDDBACKEND::pfnRename */
699static int rawRename(void *pBackendData, const char *pszFilename)
700{
701 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
702 int rc = VINF_SUCCESS;
703 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
704
705 /* Check arguments. */
706 if ( !pImage
707 || !pszFilename
708 || !*pszFilename)
709 {
710 rc = VERR_INVALID_PARAMETER;
711 goto out;
712 }
713
714 /* Close the image. */
715 rc = rawFreeImage(pImage, false);
716 if (RT_FAILURE(rc))
717 goto out;
718
719 /* Rename the file. */
720 rc = rawFileMove(pImage, pImage->pszFilename, pszFilename, 0);
721 if (RT_FAILURE(rc))
722 {
723 /* The move failed, try to reopen the original image. */
724 int rc2 = rawOpenImage(pImage, pImage->uOpenFlags);
725 if (RT_FAILURE(rc2))
726 rc = rc2;
727
728 goto out;
729 }
730
731 /* Update pImage with the new information. */
732 pImage->pszFilename = pszFilename;
733
734 /* Open the old image with new name. */
735 rc = rawOpenImage(pImage, pImage->uOpenFlags);
736 if (RT_FAILURE(rc))
737 goto out;
738
739out:
740 LogFlowFunc(("returns %Rrc\n", rc));
741 return rc;
742}
743
744/** @copydoc VBOXHDDBACKEND::pfnClose */
745static int rawClose(void *pBackendData, bool fDelete)
746{
747 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
748 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
749 int rc;
750
751 rc = rawFreeImage(pImage, fDelete);
752 RTMemFree(pImage);
753
754 LogFlowFunc(("returns %Rrc\n", rc));
755 return rc;
756}
757
758/** @copydoc VBOXHDDBACKEND::pfnRead */
759static int rawRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
760 size_t cbToRead, size_t *pcbActuallyRead)
761{
762 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
763 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
764 int rc;
765
766 AssertPtr(pImage);
767 Assert(uOffset % 512 == 0);
768 Assert(cbToRead % 512 == 0);
769
770 if ( uOffset + cbToRead > pImage->cbSize
771 || cbToRead == 0)
772 {
773 rc = VERR_INVALID_PARAMETER;
774 goto out;
775 }
776
777 /* For sequential access do not allow to go back. */
778 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
779 && uOffset < pImage->offAccess)
780 {
781 rc = VERR_INVALID_PARAMETER;
782 goto out;
783 }
784
785 rc = rawFileReadSync(pImage, uOffset, pvBuf, cbToRead, NULL);
786 pImage->offAccess = uOffset + cbToRead;
787 if (pcbActuallyRead)
788 *pcbActuallyRead = cbToRead;
789
790out:
791 LogFlowFunc(("returns %Rrc\n", rc));
792 return rc;
793}
794
795/** @copydoc VBOXHDDBACKEND::pfnWrite */
796static int rawWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
797 size_t cbToWrite, size_t *pcbWriteProcess,
798 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
799{
800 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
801 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
802 int rc;
803
804 AssertPtr(pImage);
805 Assert(uOffset % 512 == 0);
806 Assert(cbToWrite % 512 == 0);
807
808 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
809 {
810 rc = VERR_VD_IMAGE_READ_ONLY;
811 goto out;
812 }
813
814 if ( uOffset + cbToWrite > pImage->cbSize
815 || cbToWrite == 0)
816 {
817 rc = VERR_INVALID_PARAMETER;
818 goto out;
819 }
820
821 /* For sequential access do not allow to go back. */
822 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
823 && uOffset < pImage->offAccess)
824 {
825 rc = VERR_INVALID_PARAMETER;
826 goto out;
827 }
828
829 rc = rawFileWriteSync(pImage, uOffset, pvBuf, cbToWrite, NULL);
830 pImage->offAccess = uOffset + cbToWrite;
831 if (pcbWriteProcess)
832 *pcbWriteProcess = cbToWrite;
833
834out:
835 LogFlowFunc(("returns %Rrc\n", rc));
836 return rc;
837}
838
839/** @copydoc VBOXHDDBACKEND::pfnFlush */
840static int rawFlush(void *pBackendData)
841{
842 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
843 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
844 int rc;
845
846 rc = rawFlushImage(pImage);
847 LogFlowFunc(("returns %Rrc\n", rc));
848 return rc;
849}
850
851/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
852static unsigned rawGetVersion(void *pBackendData)
853{
854 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
855 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
856
857 AssertPtr(pImage);
858
859 if (pImage)
860 return 1;
861 else
862 return 0;
863}
864
865/** @copydoc VBOXHDDBACKEND::pfnGetSize */
866static uint64_t rawGetSize(void *pBackendData)
867{
868 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
869 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
870 uint64_t cb = 0;
871
872 AssertPtr(pImage);
873
874 if (pImage && pImage->pStorage)
875 cb = pImage->cbSize;
876
877 LogFlowFunc(("returns %llu\n", cb));
878 return cb;
879}
880
881/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
882static uint64_t rawGetFileSize(void *pBackendData)
883{
884 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
885 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
886 uint64_t cb = 0;
887
888 AssertPtr(pImage);
889
890 if (pImage)
891 {
892 uint64_t cbFile;
893 if (pImage->pStorage)
894 {
895 int rc = rawFileGetSize(pImage, &cbFile);
896 if (RT_SUCCESS(rc))
897 cb += cbFile;
898 }
899 }
900
901 LogFlowFunc(("returns %lld\n", cb));
902 return cb;
903}
904
905/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
906static int rawGetPCHSGeometry(void *pBackendData,
907 PVDGEOMETRY pPCHSGeometry)
908{
909 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
910 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
911 int rc;
912
913 AssertPtr(pImage);
914
915 if (pImage)
916 {
917 if (pImage->PCHSGeometry.cCylinders)
918 {
919 *pPCHSGeometry = pImage->PCHSGeometry;
920 rc = VINF_SUCCESS;
921 }
922 else
923 rc = VERR_VD_GEOMETRY_NOT_SET;
924 }
925 else
926 rc = VERR_VD_NOT_OPENED;
927
928 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
929 return rc;
930}
931
932/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
933static int rawSetPCHSGeometry(void *pBackendData,
934 PCVDGEOMETRY pPCHSGeometry)
935{
936 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
937 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
938 int rc;
939
940 AssertPtr(pImage);
941
942 if (pImage)
943 {
944 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
945 {
946 rc = VERR_VD_IMAGE_READ_ONLY;
947 goto out;
948 }
949
950 pImage->PCHSGeometry = *pPCHSGeometry;
951 rc = VINF_SUCCESS;
952 }
953 else
954 rc = VERR_VD_NOT_OPENED;
955
956out:
957 LogFlowFunc(("returns %Rrc\n", rc));
958 return rc;
959}
960
961/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
962static int rawGetLCHSGeometry(void *pBackendData,
963 PVDGEOMETRY pLCHSGeometry)
964{
965 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
966 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
967 int rc;
968
969 AssertPtr(pImage);
970
971 if (pImage)
972 {
973 if (pImage->LCHSGeometry.cCylinders)
974 {
975 *pLCHSGeometry = pImage->LCHSGeometry;
976 rc = VINF_SUCCESS;
977 }
978 else
979 rc = VERR_VD_GEOMETRY_NOT_SET;
980 }
981 else
982 rc = VERR_VD_NOT_OPENED;
983
984 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
985 return rc;
986}
987
988/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
989static int rawSetLCHSGeometry(void *pBackendData,
990 PCVDGEOMETRY pLCHSGeometry)
991{
992 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
993 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
994 int rc;
995
996 AssertPtr(pImage);
997
998 if (pImage)
999 {
1000 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
1001 {
1002 rc = VERR_VD_IMAGE_READ_ONLY;
1003 goto out;
1004 }
1005
1006 pImage->LCHSGeometry = *pLCHSGeometry;
1007 rc = VINF_SUCCESS;
1008 }
1009 else
1010 rc = VERR_VD_NOT_OPENED;
1011
1012out:
1013 LogFlowFunc(("returns %Rrc\n", rc));
1014 return rc;
1015}
1016
1017/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
1018static unsigned rawGetImageFlags(void *pBackendData)
1019{
1020 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1021 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1022 unsigned uImageFlags;
1023
1024 AssertPtr(pImage);
1025
1026 if (pImage)
1027 uImageFlags = pImage->uImageFlags;
1028 else
1029 uImageFlags = 0;
1030
1031 LogFlowFunc(("returns %#x\n", uImageFlags));
1032 return uImageFlags;
1033}
1034
1035/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
1036static unsigned rawGetOpenFlags(void *pBackendData)
1037{
1038 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1039 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1040 unsigned uOpenFlags;
1041
1042 AssertPtr(pImage);
1043
1044 if (pImage)
1045 uOpenFlags = pImage->uOpenFlags;
1046 else
1047 uOpenFlags = 0;
1048
1049 LogFlowFunc(("returns %#x\n", uOpenFlags));
1050 return uOpenFlags;
1051}
1052
1053/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
1054static int rawSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
1055{
1056 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
1057 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1058 int rc;
1059
1060 /* Image must be opened and the new flags must be valid. */
1061 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
1062 {
1063 rc = VERR_INVALID_PARAMETER;
1064 goto out;
1065 }
1066
1067 /* Implement this operation via reopening the image. */
1068 rc = rawFreeImage(pImage, false);
1069 if (RT_FAILURE(rc))
1070 goto out;
1071 rc = rawOpenImage(pImage, uOpenFlags);
1072
1073out:
1074 LogFlowFunc(("returns %Rrc\n", rc));
1075 return rc;
1076}
1077
1078/** @copydoc VBOXHDDBACKEND::pfnGetComment */
1079static int rawGetComment(void *pBackendData, char *pszComment,
1080 size_t cbComment)
1081{
1082 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
1083 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1084 int rc;
1085
1086 AssertPtr(pImage);
1087
1088 if (pImage)
1089 rc = VERR_NOT_SUPPORTED;
1090 else
1091 rc = VERR_VD_NOT_OPENED;
1092
1093 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
1094 return rc;
1095}
1096
1097/** @copydoc VBOXHDDBACKEND::pfnSetComment */
1098static int rawSetComment(void *pBackendData, const char *pszComment)
1099{
1100 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
1101 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1102 int rc;
1103
1104 AssertPtr(pImage);
1105
1106 if (pImage)
1107 {
1108 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
1109 rc = VERR_VD_IMAGE_READ_ONLY;
1110 else
1111 rc = VERR_NOT_SUPPORTED;
1112 }
1113 else
1114 rc = VERR_VD_NOT_OPENED;
1115
1116 LogFlowFunc(("returns %Rrc\n", rc));
1117 return rc;
1118}
1119
1120/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
1121static int rawGetUuid(void *pBackendData, PRTUUID pUuid)
1122{
1123 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1124 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1125 int rc;
1126
1127 AssertPtr(pImage);
1128
1129 if (pImage)
1130 rc = VERR_NOT_SUPPORTED;
1131 else
1132 rc = VERR_VD_NOT_OPENED;
1133
1134 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1135 return rc;
1136}
1137
1138/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
1139static int rawSetUuid(void *pBackendData, PCRTUUID pUuid)
1140{
1141 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1142 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1143 int rc;
1144
1145 LogFlowFunc(("%RTuuid\n", pUuid));
1146 AssertPtr(pImage);
1147
1148 if (pImage)
1149 {
1150 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1151 rc = VERR_NOT_SUPPORTED;
1152 else
1153 rc = VERR_VD_IMAGE_READ_ONLY;
1154 }
1155 else
1156 rc = VERR_VD_NOT_OPENED;
1157
1158 LogFlowFunc(("returns %Rrc\n", rc));
1159 return rc;
1160}
1161
1162/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
1163static int rawGetModificationUuid(void *pBackendData, PRTUUID pUuid)
1164{
1165 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1166 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1167 int rc;
1168
1169 AssertPtr(pImage);
1170
1171 if (pImage)
1172 rc = VERR_NOT_SUPPORTED;
1173 else
1174 rc = VERR_VD_NOT_OPENED;
1175
1176 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1177 return rc;
1178}
1179
1180/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
1181static int rawSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
1182{
1183 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1184 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1185 int rc;
1186
1187 AssertPtr(pImage);
1188
1189 if (pImage)
1190 {
1191 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1192 rc = VERR_NOT_SUPPORTED;
1193 else
1194 rc = VERR_VD_IMAGE_READ_ONLY;
1195 }
1196 else
1197 rc = VERR_VD_NOT_OPENED;
1198
1199 LogFlowFunc(("returns %Rrc\n", rc));
1200 return rc;
1201}
1202
1203/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
1204static int rawGetParentUuid(void *pBackendData, PRTUUID pUuid)
1205{
1206 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1207 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1208 int rc;
1209
1210 AssertPtr(pImage);
1211
1212 if (pImage)
1213 rc = VERR_NOT_SUPPORTED;
1214 else
1215 rc = VERR_VD_NOT_OPENED;
1216
1217 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1218 return rc;
1219}
1220
1221/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
1222static int rawSetParentUuid(void *pBackendData, PCRTUUID pUuid)
1223{
1224 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1225 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1226 int rc;
1227
1228 AssertPtr(pImage);
1229
1230 if (pImage)
1231 {
1232 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1233 rc = VERR_NOT_SUPPORTED;
1234 else
1235 rc = VERR_VD_IMAGE_READ_ONLY;
1236 }
1237 else
1238 rc = VERR_VD_NOT_OPENED;
1239
1240 LogFlowFunc(("returns %Rrc\n", rc));
1241 return rc;
1242}
1243
1244/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
1245static int rawGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
1246{
1247 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1248 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1249 int rc;
1250
1251 AssertPtr(pImage);
1252
1253 if (pImage)
1254 rc = VERR_NOT_SUPPORTED;
1255 else
1256 rc = VERR_VD_NOT_OPENED;
1257
1258 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1259 return rc;
1260}
1261
1262/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
1263static int rawSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
1264{
1265 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1266 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1267 int rc;
1268
1269 AssertPtr(pImage);
1270
1271 if (pImage)
1272 {
1273 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1274 rc = VERR_NOT_SUPPORTED;
1275 else
1276 rc = VERR_VD_IMAGE_READ_ONLY;
1277 }
1278 else
1279 rc = VERR_VD_NOT_OPENED;
1280
1281 LogFlowFunc(("returns %Rrc\n", rc));
1282 return rc;
1283}
1284
1285/** @copydoc VBOXHDDBACKEND::pfnDump */
1286static void rawDump(void *pBackendData)
1287{
1288 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1289
1290 AssertPtr(pImage);
1291 if (pImage)
1292 {
1293 rawMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
1294 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
1295 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
1296 pImage->cbSize / 512);
1297 }
1298}
1299
1300/** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */
1301static bool rawIsAsyncIOSupported(void *pBackendData)
1302{
1303 return true;
1304}
1305
1306/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
1307static int rawAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
1308 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
1309{
1310 int rc = VINF_SUCCESS;
1311 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1312
1313 rc = rawFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead);
1314 if (RT_SUCCESS(rc))
1315 *pcbActuallyRead = cbRead;
1316
1317 return rc;
1318}
1319
1320/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
1321static int rawAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
1322 PVDIOCTX pIoCtx,
1323 size_t *pcbWriteProcess, size_t *pcbPreRead,
1324 size_t *pcbPostRead, unsigned fWrite)
1325{
1326 int rc = VINF_SUCCESS;
1327 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1328
1329 rc = rawFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL);
1330 if (RT_SUCCESS(rc))
1331 {
1332 *pcbWriteProcess = cbWrite;
1333 *pcbPostRead = 0;
1334 *pcbPreRead = 0;
1335 }
1336
1337 return rc;
1338}
1339
1340/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
1341static int rawAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
1342{
1343 int rc = VINF_SUCCESS;
1344 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1345
1346 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1347 rc = rawFileFlushAsync(pImage, pIoCtx, NULL, NULL);
1348
1349 return rc;
1350}
1351
1352
1353VBOXHDDBACKEND g_RawBackend =
1354{
1355 /* pszBackendName */
1356 "RAW",
1357 /* cbSize */
1358 sizeof(VBOXHDDBACKEND),
1359 /* uBackendCaps */
1360 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
1361 /* paFileExtensions */
1362 s_aRawFileExtensions,
1363 /* paConfigInfo */
1364 NULL,
1365 /* hPlugin */
1366 NIL_RTLDRMOD,
1367 /* pfnCheckIfValid */
1368 rawCheckIfValid,
1369 /* pfnOpen */
1370 rawOpen,
1371 /* pfnCreate */
1372 rawCreate,
1373 /* pfnRename */
1374 rawRename,
1375 /* pfnClose */
1376 rawClose,
1377 /* pfnRead */
1378 rawRead,
1379 /* pfnWrite */
1380 rawWrite,
1381 /* pfnFlush */
1382 rawFlush,
1383 /* pfnGetVersion */
1384 rawGetVersion,
1385 /* pfnGetSize */
1386 rawGetSize,
1387 /* pfnGetFileSize */
1388 rawGetFileSize,
1389 /* pfnGetPCHSGeometry */
1390 rawGetPCHSGeometry,
1391 /* pfnSetPCHSGeometry */
1392 rawSetPCHSGeometry,
1393 /* pfnGetLCHSGeometry */
1394 rawGetLCHSGeometry,
1395 /* pfnSetLCHSGeometry */
1396 rawSetLCHSGeometry,
1397 /* pfnGetImageFlags */
1398 rawGetImageFlags,
1399 /* pfnGetOpenFlags */
1400 rawGetOpenFlags,
1401 /* pfnSetOpenFlags */
1402 rawSetOpenFlags,
1403 /* pfnGetComment */
1404 rawGetComment,
1405 /* pfnSetComment */
1406 rawSetComment,
1407 /* pfnGetUuid */
1408 rawGetUuid,
1409 /* pfnSetUuid */
1410 rawSetUuid,
1411 /* pfnGetModificationUuid */
1412 rawGetModificationUuid,
1413 /* pfnSetModificationUuid */
1414 rawSetModificationUuid,
1415 /* pfnGetParentUuid */
1416 rawGetParentUuid,
1417 /* pfnSetParentUuid */
1418 rawSetParentUuid,
1419 /* pfnGetParentModificationUuid */
1420 rawGetParentModificationUuid,
1421 /* pfnSetParentModificationUuid */
1422 rawSetParentModificationUuid,
1423 /* pfnDump */
1424 rawDump,
1425 /* pfnGetTimeStamp */
1426 NULL,
1427 /* pfnGetParentTimeStamp */
1428 NULL,
1429 /* pfnSetParentTimeStamp */
1430 NULL,
1431 /* pfnGetParentFilename */
1432 NULL,
1433 /* pfnSetParentFilename */
1434 NULL,
1435 /* pfnIsAsyncIOSupported */
1436 rawIsAsyncIOSupported,
1437 /* pfnAsyncRead */
1438 rawAsyncRead,
1439 /* pfnAsyncWrite */
1440 rawAsyncWrite,
1441 /* pfnAsyncFlush */
1442 rawAsyncFlush,
1443 /* pfnComposeLocation */
1444 genericFileComposeLocation,
1445 /* pfnComposeName */
1446 genericFileComposeName,
1447 /* pfnCompact */
1448 NULL,
1449 /* pfnResize */
1450 NULL
1451};
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