VirtualBox

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

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

Storage/iSCSI+Raw+VMDK: fix incorrect error code returned by pfnCheckIfValid, triggered severe regression in the snapshot code

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

© 2023 Oracle
ContactPrivacy policyTerms of Use