VirtualBox

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

Last change on this file since 77807 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.8 KB
RevLine 
[12638]1/* $Id: RAW.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
[2358]2/** @file
[12638]3 * RawHDDCore - Raw Disk image, Core Code.
[2358]4 */
5
6/*
[76553]7 * Copyright (C) 2006-2019 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
[57358]18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
[7654]22#define LOG_GROUP LOG_GROUP_VD_RAW
[33567]23#include <VBox/vd-plugin.h>
[2358]24#include <VBox/err.h>
25
26#include <VBox/log.h>
27#include <iprt/assert.h>
28#include <iprt/alloc.h>
[33524]29#include <iprt/path.h>
[2358]30
[50988]31#include "VDBackends.h"
[66492]32#include "VDBackendsInline.h"
[50988]33
[2358]34
[57358]35/*********************************************************************************************************************************
36* Constants And Macros, Structures and Typedefs *
37*********************************************************************************************************************************/
38
[2358]39/**
[7654]40 * Raw image data structure.
[2358]41 */
[7654]42typedef struct RAWIMAGE
[2358]43{
[32536]44 /** Image name. */
[33234]45 const char *pszFilename;
[27808]46 /** Storage handle. */
[33234]47 PVDIOSTORAGE pStorage;
[2358]48
[11444]49 /** Pointer to the per-disk VD interface list. */
[33234]50 PVDINTERFACE pVDIfsDisk;
[28620]51 /** Pointer to the per-image VD interface list. */
[33234]52 PVDINTERFACE pVDIfsImage;
[38469]53 /** Error interface. */
54 PVDINTERFACEERROR pIfError;
55 /** I/O interface. */
56 PVDINTERFACEIOINT pIfIo;
[11444]57
[2358]58 /** Open flags passed by VBoxHD layer. */
[33234]59 unsigned uOpenFlags;
[2661]60 /** Image flags defined during creation or determined during open. */
[33234]61 unsigned uImageFlags;
[2358]62 /** Total size of the image. */
[33234]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;
[6291]68 /** Physical geometry of this image. */
[33234]69 VDGEOMETRY PCHSGeometry;
[6291]70 /** Logical geometry of this image. */
[33234]71 VDGEOMETRY LCHSGeometry;
[48743]72 /** Sector size of the image. */
73 uint32_t cbSector;
[66486]74 /** The static region list. */
75 VDREGIONLIST RegionList;
[7654]76} RAWIMAGE, *PRAWIMAGE;
[2358]77
[33234]78
79/** Size of write operations when filling an image with zeroes. */
80#define RAW_FILL_SIZE (128 * _1K)
81
[40399]82/** The maximum reasonable size of a floppy image (big format 2.88MB medium). */
83#define RAW_MAX_FLOPPY_IMG_SIZE (512 * 82 * 48 * 2)
[33773]84
[2358]85
[57358]86/*********************************************************************************************************************************
87* Static Variables *
88*********************************************************************************************************************************/
89
[11421]90/** NULL-terminated array of supported file extensions. */
[33524]91static const VDFILEEXTENSION s_aRawFileExtensions[] =
[11421]92{
[66211]93 {"iso", VDTYPE_OPTICAL_DISC},
94 {"cdr", VDTYPE_OPTICAL_DISC},
[33524]95 {"img", VDTYPE_FLOPPY},
96 {"ima", VDTYPE_FLOPPY},
[33786]97 {"dsk", VDTYPE_FLOPPY},
[47297]98 {"flp", VDTYPE_FLOPPY},
[35045]99 {"vfd", VDTYPE_FLOPPY},
[33524]100 {NULL, VDTYPE_INVALID}
[11421]101};
102
[2358]103
[57358]104/*********************************************************************************************************************************
105* Internal Functions *
106*********************************************************************************************************************************/
107
[7155]108/**
[32536]109 * Internal. Flush image data to disk.
110 */
111static int rawFlushImage(PRAWIMAGE pImage)
[22966]112{
113 int rc = VINF_SUCCESS;
114
[32536]115 if ( pImage->pStorage
116 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
[38469]117 rc = vdIfIoIntFileFlushSync(pImage->pIfIo, pImage->pStorage);
[22966]118
119 return rc;
120}
121
[32536]122/**
123 * Internal. Free all allocated space for representing an image except pImage,
124 * and optionally delete the image from disk.
125 */
126static int rawFreeImage(PRAWIMAGE pImage, bool fDelete)
[22966]127{
128 int rc = VINF_SUCCESS;
129
[32536]130 /* Freeing a never allocated image (e.g. because the open failed) is
131 * not signalled as an error. After all nothing bad happens. */
132 if (pImage)
133 {
134 if (pImage->pStorage)
135 {
136 /* No point updating the file that is deleted anyway. */
137 if (!fDelete)
[33234]138 {
139 /* For newly created images in sequential mode fill it to
140 * the nominal size. */
141 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
142 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
143 && pImage->fCreate)
144 {
145 /* Fill rest of image with zeroes, a must for sequential
146 * images to reach the nominal size. */
147 uint64_t uOff;
148 void *pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE);
[63784]149 if (RT_LIKELY(pvBuf))
[33234]150 {
[63784]151 uOff = pImage->offAccess;
152 /* Write data to all image blocks. */
153 while (uOff < pImage->cbSize)
154 {
155 unsigned cbChunk = (unsigned)RT_MIN(pImage->cbSize - uOff,
156 RAW_FILL_SIZE);
[33234]157
[63784]158 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
159 uOff, pvBuf, cbChunk);
160 if (RT_FAILURE(rc))
161 break;
[33234]162
[63784]163 uOff += cbChunk;
164 }
165
166 RTMemTmpFree(pvBuf);
[33234]167 }
[63784]168 else
169 rc = VERR_NO_MEMORY;
[33234]170 }
[32536]171 rawFlushImage(pImage);
[33234]172 }
[22966]173
[46613]174 rc = vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage);
[32536]175 pImage->pStorage = NULL;
176 }
177
178 if (fDelete && pImage->pszFilename)
[38469]179 vdIfIoIntFileDelete(pImage->pIfIo, pImage->pszFilename);
[32536]180 }
181
182 LogFlowFunc(("returns %Rrc\n", rc));
[22966]183 return rc;
184}
185
[2742]186/**
[7155]187 * Internal: Open an image, constructing all necessary data structures.
188 */
[7654]189static int rawOpenImage(PRAWIMAGE pImage, unsigned uOpenFlags)
[2358]190{
191 pImage->uOpenFlags = uOpenFlags;
[33234]192 pImage->fCreate = false;
[2358]193
[38469]194 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
195 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
196 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
[11435]197
[63784]198 /* Open the image. */
199 int rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename,
200 VDOpenFlagsToFileOpenFlags(uOpenFlags,
201 false /* fCreate */),
202 &pImage->pStorage);
203 if (RT_SUCCESS(rc))
[2358]204 {
[63784]205 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &pImage->cbSize);
206 if ( RT_SUCCESS(rc)
207 && !(pImage->cbSize % 512))
208 pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED;
209 else if (RT_SUCCESS(rc))
210 rc = VERR_VD_RAW_SIZE_MODULO_512;
[2358]211 }
[63784]212 /* else: Do NOT signal an appropriate error here, as the VD layer has the
213 * choice of retrying the open if it failed. */
[7155]214
[66486]215 if (RT_SUCCESS(rc))
216 {
217 PVDREGIONDESC pRegion = &pImage->RegionList.aRegions[0];
218 pImage->RegionList.fFlags = 0;
219 pImage->RegionList.cRegions = 1;
220
221 pRegion->offRegion = 0; /* Disk start. */
222 pRegion->cbBlock = pImage->cbSector;
223 pRegion->enmDataForm = VDREGIONDATAFORM_RAW;
224 pRegion->enmMetadataForm = VDREGIONMETADATAFORM_NONE;
225 pRegion->cbData = pImage->cbSector;
226 pRegion->cbMetadata = 0;
227 pRegion->cRegionBlocksOrBytes = pImage->cbSize;
228 }
229 else
[7654]230 rawFreeImage(pImage, false);
[2650]231 return rc;
232}
233
[7155]234/**
[7654]235 * Internal: Create a raw image.
[7155]236 */
[17970]237static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize,
238 unsigned uImageFlags, const char *pszComment,
[32536]239 PCVDGEOMETRY pPCHSGeometry,
240 PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags,
[63784]241 PVDINTERFACEPROGRESS pIfProgress,
[7654]242 unsigned uPercentStart, unsigned uPercentSpan)
[2650]243{
[62747]244 RT_NOREF1(pszComment);
[63784]245 int rc = VINF_SUCCESS;
[2650]246
[63784]247 pImage->fCreate = true;
248 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;
249 pImage->uImageFlags = uImageFlags | VD_IMAGE_FLAGS_FIXED;
[7654]250 pImage->PCHSGeometry = *pPCHSGeometry;
251 pImage->LCHSGeometry = *pLCHSGeometry;
[63784]252 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
253 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
[38469]254 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
[11435]255
[63784]256 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_DIFF))
[38469]257 {
[63784]258 /* Create image file. */
259 uint32_t fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */);
260 if (uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)
261 fOpen &= ~RTFILE_O_READ;
262 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage);
263 if (RT_SUCCESS(rc))
264 {
265 if (!(uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
266 {
267 RTFOFF cbFree = 0;
[22966]268
[63784]269 /* Check the free space on the disk and leave early if there is not
270 * sufficient space available. */
271 rc = vdIfIoIntFileGetFreeSpace(pImage->pIfIo, pImage->pszFilename, &cbFree);
272 if (RT_FAILURE(rc) /* ignore errors */ || ((uint64_t)cbFree >= cbSize))
273 {
274 rc = vdIfIoIntFileSetAllocationSize(pImage->pIfIo, pImage->pStorage, cbSize, 0 /* fFlags */,
[63811]275 pIfProgress, uPercentStart, uPercentSpan);
[63784]276 if (RT_SUCCESS(rc))
277 {
278 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 98 / 100);
[7654]279
[63784]280 pImage->cbSize = cbSize;
281 rc = rawFlushImage(pImage);
282 }
283 }
284 else
285 rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
286 }
[66110]287 else
288 {
289 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbSize);
290 if (RT_SUCCESS(rc))
291 pImage->cbSize = cbSize;
292 }
[33234]293 }
[63784]294 else
295 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename);
[2650]296 }
[63784]297 else
298 rc = vdIfError(pImage->pIfError, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename);
[2650]299
[63784]300 if (RT_SUCCESS(rc))
[66486]301 {
302 PVDREGIONDESC pRegion = &pImage->RegionList.aRegions[0];
303 pImage->RegionList.fFlags = 0;
304 pImage->RegionList.cRegions = 1;
305
306 pRegion->offRegion = 0; /* Disk start. */
307 pRegion->cbBlock = pImage->cbSector;
308 pRegion->enmDataForm = VDREGIONDATAFORM_RAW;
309 pRegion->enmMetadataForm = VDREGIONMETADATAFORM_NONE;
310 pRegion->cbData = pImage->cbSector;
311 pRegion->cbMetadata = 0;
312 pRegion->cRegionBlocksOrBytes = pImage->cbSize;
313
[63784]314 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan);
[66486]315 }
[6291]316
[11266]317 if (RT_FAILURE(rc))
[7654]318 rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
[2358]319 return rc;
320}
321
[7155]322
[63802]323/** @copydoc VDIMAGEBACKEND::pfnProbe */
324static DECLCALLBACK(int) rawProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
325 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
[2358]326{
[62747]327 RT_NOREF1(pVDIfsDisk);
[33524]328 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
329 PVDIOSTORAGE pStorage = NULL;
[63784]330 PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage);
[7155]331
[38469]332 AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
[63784]333 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
[33524]334
335 /*
336 * Open the file and read the footer.
337 */
[63784]338 int rc = vdIfIoIntFileOpen(pIfIo, pszFilename,
339 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
340 false /* fCreate */),
341 &pStorage);
[33524]342 if (RT_SUCCESS(rc))
[62747]343 {
[63784]344 uint64_t cbFile;
345 const char *pszSuffix = RTPathSuffix(pszFilename);
[38469]346 rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile);
[33524]347
[62747]348 /* Try to guess the image type based on the extension. */
349 if ( RT_SUCCESS(rc)
350 && pszSuffix)
[33524]351 {
[62747]352 if ( !RTStrICmp(pszSuffix, ".iso")
353 || !RTStrICmp(pszSuffix, ".cdr")) /* DVD images. */
[33524]354 {
[62747]355 /* Note that there are ISO images smaller than 1 MB; it is impossible to distinguish
356 * between raw floppy and CD images based on their size (and cannot be reliably done
357 * based on contents, either).
[69673]358 * bird: Not sure what this comment is mumbling about, the test below is 32KB not 1MB.
[62747]359 */
360 if (cbFile % 2048)
361 rc = VERR_VD_RAW_SIZE_MODULO_2048;
362 else if (cbFile <= 32768)
363 rc = VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL;
364 else
365 {
[66211]366 *penmType = VDTYPE_OPTICAL_DISC;
[62747]367 rc = VINF_SUCCESS;
368 }
[33524]369 }
[62747]370 else if ( !RTStrICmp(pszSuffix, ".img")
371 || !RTStrICmp(pszSuffix, ".ima")
372 || !RTStrICmp(pszSuffix, ".dsk")
373 || !RTStrICmp(pszSuffix, ".flp")
374 || !RTStrICmp(pszSuffix, ".vfd")) /* Floppy images */
[33524]375 {
[62747]376 if (cbFile % 512)
377 rc = VERR_VD_RAW_SIZE_MODULO_512;
378 else if (cbFile > RAW_MAX_FLOPPY_IMG_SIZE)
379 rc = VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG;
380 else
381 {
382 *penmType = VDTYPE_FLOPPY;
383 rc = VINF_SUCCESS;
384 }
[33524]385 }
[62747]386 else
387 rc = VERR_VD_RAW_INVALID_HEADER;
[33524]388 }
[35480]389 else
390 rc = VERR_VD_RAW_INVALID_HEADER;
[33524]391 }
392
393 if (pStorage)
[38469]394 vdIfIoIntFileClose(pIfIo, pStorage);
[33524]395
[11284]396 LogFlowFunc(("returns %Rrc\n", rc));
[6291]397 return rc;
398}
399
[63784]400/** @copydoc VDIMAGEBACKEND::pfnOpen */
[57388]401static DECLCALLBACK(int) rawOpen(const char *pszFilename, unsigned uOpenFlags,
402 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
403 VDTYPE enmType, void **ppBackendData)
[6291]404{
[63784]405 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n",
406 pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData));
[2650]407 int rc;
[7654]408 PRAWIMAGE pImage;
[2358]409
[2650]410 /* Check open flags. All valid flags are supported. */
[63784]411 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
412 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
[2358]413
[66486]414 pImage = (PRAWIMAGE)RTMemAllocZ(RT_UOFFSETOF(RAWIMAGE, RegionList.aRegions[1]));
[63784]415 if (RT_LIKELY(pImage))
[2358]416 {
[63784]417 pImage->pszFilename = pszFilename;
418 pImage->pStorage = NULL;
419 pImage->pVDIfsDisk = pVDIfsDisk;
420 pImage->pVDIfsImage = pVDIfsImage;
[2358]421
[66489]422 if (enmType == VDTYPE_OPTICAL_DISC)
423 pImage->cbSector = 2048;
424 else
425 pImage->cbSector = 512;
426
[63784]427 rc = rawOpenImage(pImage, uOpenFlags);
428 if (RT_SUCCESS(rc))
429 *ppBackendData = pImage;
[48743]430 else
[63784]431 RTMemFree(pImage);
[48743]432 }
[23913]433 else
[63784]434 rc = VERR_NO_MEMORY;
[2358]435
[11284]436 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
[2358]437 return rc;
438}
439
[63784]440/** @copydoc VDIMAGEBACKEND::pfnCreate */
[57388]441static DECLCALLBACK(int) rawCreate(const char *pszFilename, uint64_t cbSize,
442 unsigned uImageFlags, const char *pszComment,
443 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
444 PCRTUUID pUuid, unsigned uOpenFlags,
445 unsigned uPercentStart, unsigned uPercentSpan,
446 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
447 PVDINTERFACE pVDIfsOperation, VDTYPE enmType,
448 void **ppBackendData)
[2564]449{
[62747]450 RT_NOREF1(pUuid);
[54430]451 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 enmType=%u ppBackendData=%#p",
452 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, enmType, ppBackendData));
[2650]453
[54430]454 /* Check the VD container type. Yes, hard disk must be allowed, otherwise
455 * various tools using this backend for hard disk images will fail. */
[66211]456 if (enmType != VDTYPE_HDD && enmType != VDTYPE_OPTICAL_DISC && enmType != VDTYPE_FLOPPY)
[63784]457 return VERR_VD_INVALID_TYPE;
[54430]458
[63784]459 int rc = VINF_SUCCESS;
460 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);
[2650]461
[63784]462 /* Check arguments. */
463 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
464 AssertReturn( VALID_PTR(pszFilename)
465 && *pszFilename
466 && VALID_PTR(pPCHSGeometry)
467 && VALID_PTR(pLCHSGeometry), VERR_INVALID_PARAMETER);
[7155]468
[66486]469 PRAWIMAGE pImage = (PRAWIMAGE)RTMemAllocZ(RT_UOFFSETOF(RAWIMAGE, RegionList.aRegions[1]));
[63784]470 if (RT_LIKELY(pImage))
[2650]471 {
[63784]472 pImage->pszFilename = pszFilename;
473 pImage->pStorage = NULL;
474 pImage->pVDIfsDisk = pVDIfsDisk;
475 pImage->pVDIfsImage = pVDIfsImage;
[2650]476
[63784]477 rc = rawCreateImage(pImage, cbSize, uImageFlags, pszComment,
478 pPCHSGeometry, pLCHSGeometry, uOpenFlags,
479 pIfProgress, uPercentStart, uPercentSpan);
480 if (RT_SUCCESS(rc))
[2650]481 {
[63784]482 /* So far the image is opened in read/write mode. Make sure the
483 * image is opened in read-only mode if the caller requested that. */
484 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
[23913]485 {
[63784]486 rawFreeImage(pImage, false);
487 rc = rawOpenImage(pImage, uOpenFlags);
[23913]488 }
[63784]489
490 if (RT_SUCCESS(rc))
491 *ppBackendData = pImage;
[2650]492 }
[63784]493
494 if (RT_FAILURE(rc))
495 RTMemFree(pImage);
[2650]496 }
[23913]497 else
[63784]498 rc = VERR_NO_MEMORY;
[2650]499
[11284]500 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
[2650]501 return rc;
[2564]502}
503
[63784]504/** @copydoc VDIMAGEBACKEND::pfnRename */
[57388]505static DECLCALLBACK(int) rawRename(void *pBackendData, const char *pszFilename)
[6291]506{
[7155]507 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
[32536]508 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[7155]509
[63784]510 AssertReturn((pImage && pszFilename && *pszFilename), VERR_INVALID_PARAMETER);
[32536]511
512 /* Close the image. */
[63784]513 int rc = rawFreeImage(pImage, false);
514 if (RT_SUCCESS(rc))
[32536]515 {
[63784]516 /* Rename the file. */
517 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0);
518 if (RT_SUCCESS(rc))
519 {
520 /* Update pImage with the new information. */
521 pImage->pszFilename = pszFilename;
[32536]522
[63784]523 /* Open the old image with new name. */
524 rc = rawOpenImage(pImage, pImage->uOpenFlags);
525 }
526 else
527 {
528 /* The move failed, try to reopen the original image. */
529 int rc2 = rawOpenImage(pImage, pImage->uOpenFlags);
530 if (RT_FAILURE(rc2))
531 rc = rc2;
532 }
[32536]533 }
534
[11284]535 LogFlowFunc(("returns %Rrc\n", rc));
[7155]536 return rc;
[6291]537}
538
[63784]539/** @copydoc VDIMAGEBACKEND::pfnClose */
[57388]540static DECLCALLBACK(int) rawClose(void *pBackendData, bool fDelete)
[2358]541{
[7155]542 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
[7654]543 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[63784]544 int rc = rawFreeImage(pImage, fDelete);
[32536]545 RTMemFree(pImage);
[2358]546
[11284]547 LogFlowFunc(("returns %Rrc\n", rc));
[2358]548 return rc;
549}
550
[63784]551/** @copydoc VDIMAGEBACKEND::pfnRead */
[64272]552static DECLCALLBACK(int) rawRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
[57388]553 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
[2358]554{
[44252]555 int rc = VINF_SUCCESS;
[7654]556 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[2358]557
[58258]558 /* For sequential access do not allow to go back. */
559 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
560 && uOffset < pImage->offAccess)
561 {
562 *pcbActuallyRead = 0;
563 return VERR_INVALID_PARAMETER;
564 }
565
[44252]566 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,
[64272]567 pIoCtx, cbToRead);
[44252]568 if (RT_SUCCESS(rc))
[58258]569 {
[64272]570 *pcbActuallyRead = cbToRead;
571 pImage->offAccess = uOffset + cbToRead;
[58258]572 }
[2358]573
574 return rc;
575}
576
[63784]577/** @copydoc VDIMAGEBACKEND::pfnWrite */
[64272]578static DECLCALLBACK(int) rawWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
[57388]579 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
580 size_t *pcbPostRead, unsigned fWrite)
[2358]581{
[62747]582 RT_NOREF1(fWrite);
[44252]583 int rc = VINF_SUCCESS;
[7654]584 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[2358]585
[58258]586 /* For sequential access do not allow to go back. */
587 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
588 && uOffset < pImage->offAccess)
589 {
590 *pcbWriteProcess = 0;
591 *pcbPostRead = 0;
592 *pcbPreRead = 0;
593 return VERR_INVALID_PARAMETER;
594 }
595
[44252]596 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, uOffset,
[64272]597 pIoCtx, cbToWrite, NULL, NULL);
[44252]598 if (RT_SUCCESS(rc))
[2358]599 {
[64272]600 *pcbWriteProcess = cbToWrite;
[44252]601 *pcbPostRead = 0;
602 *pcbPreRead = 0;
[64272]603 pImage->offAccess = uOffset + cbToWrite;
[2358]604 }
605
606 return rc;
607}
608
[63784]609/** @copydoc VDIMAGEBACKEND::pfnFlush */
[57388]610static DECLCALLBACK(int) rawFlush(void *pBackendData, PVDIOCTX pIoCtx)
[2358]611{
[44252]612 int rc = VINF_SUCCESS;
[7654]613 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[2358]614
[44252]615 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
616 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx,
617 NULL, NULL);
618
[2358]619 return rc;
620}
621
[63784]622/** @copydoc VDIMAGEBACKEND::pfnGetVersion */
[57388]623static DECLCALLBACK(unsigned) rawGetVersion(void *pBackendData)
[6291]624{
[7155]625 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
[7654]626 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[6291]627
[63784]628 AssertPtrReturn(pImage, 0);
[6291]629
[63784]630 return 1;
[6291]631}
632
[63784]633/** @copydoc VDIMAGEBACKEND::pfnGetFileSize */
[57388]634static DECLCALLBACK(uint64_t) rawGetFileSize(void *pBackendData)
[2358]635{
[7155]636 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
[7654]637 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[6291]638
[63784]639 AssertPtrReturn(pImage, 0);
[6291]640
[63784]641 uint64_t cbFile = 0;
642 if (pImage->pStorage)
[6291]643 {
[63784]644 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
645 if (RT_FAILURE(rc))
646 cbFile = 0; /* Make sure it is 0 */
[6291]647 }
[7155]648
[63784]649 LogFlowFunc(("returns %lld\n", cbFile));
650 return cbFile;
[6291]651}
652
[63784]653/** @copydoc VDIMAGEBACKEND::pfnGetPCHSGeometry */
[57388]654static DECLCALLBACK(int) rawGetPCHSGeometry(void *pBackendData,
655 PVDGEOMETRY pPCHSGeometry)
[6291]656{
[7155]657 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
[7654]658 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[63784]659 int rc = VINF_SUCCESS;
[2358]660
[63784]661 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
[2358]662
[63784]663 if (pImage->PCHSGeometry.cCylinders)
664 *pPCHSGeometry = pImage->PCHSGeometry;
[2358]665 else
[63784]666 rc = VERR_VD_GEOMETRY_NOT_SET;
[7155]667
[11284]668 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
[2358]669 return rc;
670}
671
[63784]672/** @copydoc VDIMAGEBACKEND::pfnSetPCHSGeometry */
[57388]673static DECLCALLBACK(int) rawSetPCHSGeometry(void *pBackendData,
674 PCVDGEOMETRY pPCHSGeometry)
[2358]675{
[63784]676 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n",
677 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
[7654]678 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[63784]679 int rc = VINF_SUCCESS;
[2358]680
[63784]681 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
[2358]682
[63784]683 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
684 rc = VERR_VD_IMAGE_READ_ONLY;
685 else
[6291]686 pImage->PCHSGeometry = *pPCHSGeometry;
[2358]687
[11284]688 LogFlowFunc(("returns %Rrc\n", rc));
[2358]689 return rc;
690}
691
[63784]692/** @copydoc VDIMAGEBACKEND::pfnGetLCHSGeometry */
[57388]693static DECLCALLBACK(int) rawGetLCHSGeometry(void *pBackendData,
694 PVDGEOMETRY pLCHSGeometry)
[2358]695{
[7155]696 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
[7654]697 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[63784]698 int rc = VINF_SUCCESS;
[2358]699
[63784]700 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
[2358]701
[63784]702 if (pImage->LCHSGeometry.cCylinders)
703 *pLCHSGeometry = pImage->LCHSGeometry;
[2358]704 else
[63784]705 rc = VERR_VD_GEOMETRY_NOT_SET;
[7155]706
[11284]707 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
[2358]708 return rc;
709}
710
[63784]711/** @copydoc VDIMAGEBACKEND::pfnSetLCHSGeometry */
[57388]712static DECLCALLBACK(int) rawSetLCHSGeometry(void *pBackendData,
713 PCVDGEOMETRY pLCHSGeometry)
[2358]714{
[63784]715 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n",
716 pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
[7654]717 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[63784]718 int rc = VINF_SUCCESS;
[2358]719
[63784]720 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
[2358]721
[63784]722 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
723 rc = VERR_VD_IMAGE_READ_ONLY;
724 else
[6291]725 pImage->LCHSGeometry = *pLCHSGeometry;
726
[11284]727 LogFlowFunc(("returns %Rrc\n", rc));
[2358]728 return rc;
729}
730
[66486]731/** @copydoc VDIMAGEBACKEND::pfnQueryRegions */
732static DECLCALLBACK(int) rawQueryRegions(void *pBackendData, PCVDREGIONLIST *ppRegionList)
733{
734 LogFlowFunc(("pBackendData=%#p ppRegionList=%#p\n", pBackendData, ppRegionList));
735 PRAWIMAGE pThis = (PRAWIMAGE)pBackendData;
736
737 AssertPtrReturn(pThis, VERR_VD_NOT_OPENED);
738
739 *ppRegionList = &pThis->RegionList;
740 LogFlowFunc(("returns %Rrc\n", VINF_SUCCESS));
741 return VINF_SUCCESS;
742}
743
744/** @copydoc VDIMAGEBACKEND::pfnRegionListRelease */
745static DECLCALLBACK(void) rawRegionListRelease(void *pBackendData, PCVDREGIONLIST pRegionList)
746{
747 RT_NOREF1(pRegionList);
748 LogFlowFunc(("pBackendData=%#p pRegionList=%#p\n", pBackendData, pRegionList));
749 PRAWIMAGE pThis = (PRAWIMAGE)pBackendData;
750 AssertPtr(pThis); RT_NOREF(pThis);
751
752 /* Nothing to do here. */
753}
754
[63784]755/** @copydoc VDIMAGEBACKEND::pfnGetImageFlags */
[57388]756static DECLCALLBACK(unsigned) rawGetImageFlags(void *pBackendData)
[6291]757{
[7155]758 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
[7654]759 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[6291]760
[63784]761 AssertPtrReturn(pImage, 0);
[6291]762
[63784]763 LogFlowFunc(("returns %#x\n", pImage->uImageFlags));
764 return pImage->uImageFlags;
[6291]765}
766
[63784]767/** @copydoc VDIMAGEBACKEND::pfnGetOpenFlags */
[57388]768static DECLCALLBACK(unsigned) rawGetOpenFlags(void *pBackendData)
[2358]769{
[7155]770 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
[7654]771 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[2358]772
[63784]773 AssertPtrReturn(pImage, 0);
[2358]774
[63784]775 LogFlowFunc(("returns %#x\n", pImage->uOpenFlags));
776 return pImage->uOpenFlags;
[2358]777}
778
[63784]779/** @copydoc VDIMAGEBACKEND::pfnSetOpenFlags */
[57388]780static DECLCALLBACK(int) rawSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
[2358]781{
[7155]782 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
[7654]783 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[63784]784 int rc = VINF_SUCCESS;
[2358]785
[33182]786 /* Image must be opened and the new flags must be valid. */
[44232]787 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
788 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
789 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
[63784]790 rc = VERR_INVALID_PARAMETER;
791 else
[2358]792 {
[63784]793 /* Implement this operation via reopening the image. */
794 rc = rawFreeImage(pImage, false);
795 if (RT_SUCCESS(rc))
796 rc = rawOpenImage(pImage, uOpenFlags);
[2358]797 }
798
[11284]799 LogFlowFunc(("returns %Rrc\n", rc));
[2358]800 return rc;
801}
802
[63784]803/** @copydoc VDIMAGEBACKEND::pfnGetComment */
[66492]804VD_BACKEND_CALLBACK_GET_COMMENT_DEF_NOT_SUPPORTED(rawGetComment);
[2742]805
[63784]806/** @copydoc VDIMAGEBACKEND::pfnSetComment */
[66492]807VD_BACKEND_CALLBACK_SET_COMMENT_DEF_NOT_SUPPORTED(rawSetComment, PRAWIMAGE);
[2742]808
[63784]809/** @copydoc VDIMAGEBACKEND::pfnGetUuid */
[66492]810VD_BACKEND_CALLBACK_GET_UUID_DEF_NOT_SUPPORTED(rawGetUuid);
[2358]811
[63784]812/** @copydoc VDIMAGEBACKEND::pfnSetUuid */
[66492]813VD_BACKEND_CALLBACK_SET_UUID_DEF_NOT_SUPPORTED(rawSetUuid, PRAWIMAGE);
[2358]814
[63784]815/** @copydoc VDIMAGEBACKEND::pfnGetModificationUuid */
[66492]816VD_BACKEND_CALLBACK_GET_UUID_DEF_NOT_SUPPORTED(rawGetModificationUuid);
[2358]817
[63784]818/** @copydoc VDIMAGEBACKEND::pfnSetModificationUuid */
[66492]819VD_BACKEND_CALLBACK_SET_UUID_DEF_NOT_SUPPORTED(rawSetModificationUuid, PRAWIMAGE);
[2358]820
[63784]821/** @copydoc VDIMAGEBACKEND::pfnGetParentUuid */
[66492]822VD_BACKEND_CALLBACK_GET_UUID_DEF_NOT_SUPPORTED(rawGetParentUuid);
[2358]823
[63784]824/** @copydoc VDIMAGEBACKEND::pfnSetParentUuid */
[66492]825VD_BACKEND_CALLBACK_SET_UUID_DEF_NOT_SUPPORTED(rawSetParentUuid, PRAWIMAGE);
[2358]826
[63784]827/** @copydoc VDIMAGEBACKEND::pfnGetParentModificationUuid */
[66492]828VD_BACKEND_CALLBACK_GET_UUID_DEF_NOT_SUPPORTED(rawGetParentModificationUuid);
[7155]829
[63784]830/** @copydoc VDIMAGEBACKEND::pfnSetParentModificationUuid */
[66492]831VD_BACKEND_CALLBACK_SET_UUID_DEF_NOT_SUPPORTED(rawSetParentModificationUuid, PRAWIMAGE);
[7155]832
[63784]833/** @copydoc VDIMAGEBACKEND::pfnDump */
[57388]834static DECLCALLBACK(void) rawDump(void *pBackendData)
[6291]835{
[7654]836 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
[2358]837
[63784]838 AssertPtrReturnVoid(pImage);
839 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
840 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
841 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
842 pImage->cbSize / 512);
[6291]843}
844
[28154]845
846
[63781]847const VDIMAGEBACKEND g_RawBackend =
[2358]848{
[63905]849 /* u32Version */
850 VD_IMGBACKEND_VERSION,
[6291]851 /* pszBackendName */
[33524]852 "RAW",
[7780]853 /* uBackendCaps */
[32536]854 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
[33524]855 /* paFileExtensions */
856 s_aRawFileExtensions,
[11484]857 /* paConfigInfo */
858 NULL,
[63802]859 /* pfnProbe */
860 rawProbe,
[2358]861 /* pfnOpen */
[7654]862 rawOpen,
[2564]863 /* pfnCreate */
[7654]864 rawCreate,
[6291]865 /* pfnRename */
[7654]866 rawRename,
[2358]867 /* pfnClose */
[7654]868 rawClose,
[2358]869 /* pfnRead */
[7654]870 rawRead,
[2358]871 /* pfnWrite */
[7654]872 rawWrite,
[2358]873 /* pfnFlush */
[7654]874 rawFlush,
[44252]875 /* pfnDiscard */
876 NULL,
[6291]877 /* pfnGetVersion */
[7654]878 rawGetVersion,
[6291]879 /* pfnGetFileSize */
[7654]880 rawGetFileSize,
[6291]881 /* pfnGetPCHSGeometry */
[7654]882 rawGetPCHSGeometry,
[6291]883 /* pfnSetPCHSGeometry */
[7654]884 rawSetPCHSGeometry,
[6291]885 /* pfnGetLCHSGeometry */
[7654]886 rawGetLCHSGeometry,
[6291]887 /* pfnSetLCHSGeometry */
[7654]888 rawSetLCHSGeometry,
[66110]889 /* pfnQueryRegions */
[66486]890 rawQueryRegions,
[66110]891 /* pfnRegionListRelease */
[66486]892 rawRegionListRelease,
[6291]893 /* pfnGetImageFlags */
[7654]894 rawGetImageFlags,
[2358]895 /* pfnGetOpenFlags */
[7654]896 rawGetOpenFlags,
[2358]897 /* pfnSetOpenFlags */
[7654]898 rawSetOpenFlags,
[2742]899 /* pfnGetComment */
[7654]900 rawGetComment,
[2742]901 /* pfnSetComment */
[7654]902 rawSetComment,
[2358]903 /* pfnGetUuid */
[7654]904 rawGetUuid,
[2742]905 /* pfnSetUuid */
[7654]906 rawSetUuid,
[2358]907 /* pfnGetModificationUuid */
[7654]908 rawGetModificationUuid,
[2358]909 /* pfnSetModificationUuid */
[7654]910 rawSetModificationUuid,
[2358]911 /* pfnGetParentUuid */
[7654]912 rawGetParentUuid,
[2358]913 /* pfnSetParentUuid */
[7654]914 rawSetParentUuid,
[7155]915 /* pfnGetParentModificationUuid */
[7654]916 rawGetParentModificationUuid,
[7155]917 /* pfnSetParentModificationUuid */
[7654]918 rawSetParentModificationUuid,
[6291]919 /* pfnDump */
[10715]920 rawDump,
[58132]921 /* pfnGetTimestamp */
[32536]922 NULL,
[58132]923 /* pfnGetParentTimestamp */
[32536]924 NULL,
[58132]925 /* pfnSetParentTimestamp */
[32536]926 NULL,
[10715]927 /* pfnGetParentFilename */
[32536]928 NULL,
[10715]929 /* pfnSetParentFilename */
[32536]930 NULL,
[14967]931 /* pfnComposeLocation */
932 genericFileComposeLocation,
933 /* pfnComposeName */
[26291]934 genericFileComposeName,
935 /* pfnCompact */
[31776]936 NULL,
937 /* pfnResize */
[38621]938 NULL,
[39519]939 /* pfnRepair */
[50988]940 NULL,
941 /* pfnTraverseMetadata */
[63905]942 NULL,
943 /* u32VersionEnd */
944 VD_IMGBACKEND_VERSION
[2358]945};
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