VirtualBox

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

Last change on this file since 96238 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.9 KB
Line 
1/* $Id: RAW.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * RawHDDCore - Raw Disk image, Core Code.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_VD_RAW
23#include <VBox/vd-plugin.h>
24#include <VBox/err.h>
25
26#include <VBox/log.h>
27#include <iprt/assert.h>
28#include <iprt/alloc.h>
29#include <iprt/path.h>
30#include <iprt/formats/iso9660.h>
31#include <iprt/formats/udf.h>
32
33#include "VDBackends.h"
34#include "VDBackendsInline.h"
35
36
37/*********************************************************************************************************************************
38* Constants And Macros, Structures and Typedefs *
39*********************************************************************************************************************************/
40
41/**
42 * Raw image data structure.
43 */
44typedef struct RAWIMAGE
45{
46 /** Image name. */
47 const char *pszFilename;
48 /** Storage handle. */
49 PVDIOSTORAGE pStorage;
50
51 /** Pointer to the per-disk VD interface list. */
52 PVDINTERFACE pVDIfsDisk;
53 /** Pointer to the per-image VD interface list. */
54 PVDINTERFACE pVDIfsImage;
55 /** Error interface. */
56 PVDINTERFACEERROR pIfError;
57 /** I/O interface. */
58 PVDINTERFACEIOINT pIfIo;
59
60 /** Open flags passed by VBoxHD layer. */
61 unsigned uOpenFlags;
62 /** Image flags defined during creation or determined during open. */
63 unsigned uImageFlags;
64 /** Total size of the image. */
65 uint64_t cbSize;
66 /** Position in the image (only truly used for sequential access). */
67 uint64_t offAccess;
68 /** Flag if this is a newly created image. */
69 bool fCreate;
70 /** Physical geometry of this image. */
71 VDGEOMETRY PCHSGeometry;
72 /** Logical geometry of this image. */
73 VDGEOMETRY LCHSGeometry;
74 /** Sector size of the image. */
75 uint32_t cbSector;
76 /** The static region list. */
77 VDREGIONLIST RegionList;
78} RAWIMAGE, *PRAWIMAGE;
79
80
81/** Size of write operations when filling an image with zeroes. */
82#define RAW_FILL_SIZE (128 * _1K)
83
84/** The maximum reasonable size of a floppy image (big format 2.88MB medium). */
85#define RAW_MAX_FLOPPY_IMG_SIZE (512 * 82 * 48 * 2)
86
87
88/*********************************************************************************************************************************
89* Static Variables *
90*********************************************************************************************************************************/
91
92/** NULL-terminated array of supported file extensions. */
93static const VDFILEEXTENSION s_aRawFileExtensions[] =
94{
95 {"iso", VDTYPE_OPTICAL_DISC},
96 {"cdr", VDTYPE_OPTICAL_DISC},
97 {"img", VDTYPE_FLOPPY},
98 {"ima", VDTYPE_FLOPPY},
99 {"dsk", VDTYPE_FLOPPY},
100 {"flp", VDTYPE_FLOPPY},
101 {"vfd", VDTYPE_FLOPPY},
102 {NULL, VDTYPE_INVALID}
103};
104
105
106/*********************************************************************************************************************************
107* Internal Functions *
108*********************************************************************************************************************************/
109
110/**
111 * Internal. Flush image data to disk.
112 */
113static int rawFlushImage(PRAWIMAGE pImage)
114{
115 int rc = VINF_SUCCESS;
116
117 if ( pImage->pStorage
118 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
119 rc = vdIfIoIntFileFlushSync(pImage->pIfIo, pImage->pStorage);
120
121 return rc;
122}
123
124/**
125 * Internal. Free all allocated space for representing an image except pImage,
126 * and optionally delete the image from disk.
127 */
128static int rawFreeImage(PRAWIMAGE pImage, bool fDelete)
129{
130 int rc = VINF_SUCCESS;
131
132 /* Freeing a never allocated image (e.g. because the open failed) is
133 * not signalled as an error. After all nothing bad happens. */
134 if (pImage)
135 {
136 if (pImage->pStorage)
137 {
138 /* No point updating the file that is deleted anyway. */
139 if (!fDelete)
140 {
141 /* For newly created images in sequential mode fill it to
142 * the nominal size. */
143 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
144 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
145 && pImage->fCreate)
146 {
147 /* Fill rest of image with zeroes, a must for sequential
148 * images to reach the nominal size. */
149 uint64_t uOff;
150 void *pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE);
151 if (RT_LIKELY(pvBuf))
152 {
153 uOff = pImage->offAccess;
154 /* Write data to all image blocks. */
155 while (uOff < pImage->cbSize)
156 {
157 unsigned cbChunk = (unsigned)RT_MIN(pImage->cbSize - uOff,
158 RAW_FILL_SIZE);
159
160 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
161 uOff, pvBuf, cbChunk);
162 if (RT_FAILURE(rc))
163 break;
164
165 uOff += cbChunk;
166 }
167
168 RTMemTmpFree(pvBuf);
169 }
170 else
171 rc = VERR_NO_MEMORY;
172 }
173 rawFlushImage(pImage);
174 }
175
176 rc = vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage);
177 pImage->pStorage = NULL;
178 }
179
180 if (fDelete && pImage->pszFilename)
181 vdIfIoIntFileDelete(pImage->pIfIo, pImage->pszFilename);
182 }
183
184 LogFlowFunc(("returns %Rrc\n", rc));
185 return rc;
186}
187
188/**
189 * Internal: Open an image, constructing all necessary data structures.
190 */
191static int rawOpenImage(PRAWIMAGE pImage, unsigned uOpenFlags)
192{
193 pImage->uOpenFlags = uOpenFlags;
194 pImage->fCreate = false;
195
196 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
197 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
198 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
199
200 /* Open the image. */
201 int rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename,
202 VDOpenFlagsToFileOpenFlags(uOpenFlags,
203 false /* fCreate */),
204 &pImage->pStorage);
205 if (RT_SUCCESS(rc))
206 {
207 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &pImage->cbSize);
208 if ( RT_SUCCESS(rc)
209 && !(pImage->cbSize % 512))
210 pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED;
211 else if (RT_SUCCESS(rc))
212 rc = VERR_VD_RAW_SIZE_MODULO_512;
213 }
214 /* else: Do NOT signal an appropriate error here, as the VD layer has the
215 * choice of retrying the open if it failed. */
216
217 if (RT_SUCCESS(rc))
218 {
219 PVDREGIONDESC pRegion = &pImage->RegionList.aRegions[0];
220 pImage->RegionList.fFlags = 0;
221 pImage->RegionList.cRegions = 1;
222
223 pRegion->offRegion = 0; /* Disk start. */
224 pRegion->cbBlock = pImage->cbSector;
225 pRegion->enmDataForm = VDREGIONDATAFORM_RAW;
226 pRegion->enmMetadataForm = VDREGIONMETADATAFORM_NONE;
227 pRegion->cbData = pImage->cbSector;
228 pRegion->cbMetadata = 0;
229 pRegion->cRegionBlocksOrBytes = pImage->cbSize;
230 }
231 else
232 rawFreeImage(pImage, false);
233 return rc;
234}
235
236/**
237 * Internal: Create a raw image.
238 */
239static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize,
240 unsigned uImageFlags, const char *pszComment,
241 PCVDGEOMETRY pPCHSGeometry,
242 PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags,
243 PVDINTERFACEPROGRESS pIfProgress,
244 unsigned uPercentStart, unsigned uPercentSpan)
245{
246 RT_NOREF1(pszComment);
247 int rc = VINF_SUCCESS;
248
249 pImage->fCreate = true;
250 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;
251 pImage->uImageFlags = uImageFlags | VD_IMAGE_FLAGS_FIXED;
252 pImage->PCHSGeometry = *pPCHSGeometry;
253 pImage->LCHSGeometry = *pLCHSGeometry;
254 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
255 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
256 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
257
258 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_DIFF))
259 {
260 /* Create image file. */
261 uint32_t fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */);
262 if (uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)
263 fOpen &= ~RTFILE_O_READ;
264 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage);
265 if (RT_SUCCESS(rc))
266 {
267 if (!(uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
268 {
269 RTFOFF cbFree = 0;
270
271 /* Check the free space on the disk and leave early if there is not
272 * sufficient space available. */
273 rc = vdIfIoIntFileGetFreeSpace(pImage->pIfIo, pImage->pszFilename, &cbFree);
274 if (RT_FAILURE(rc) /* ignore errors */ || ((uint64_t)cbFree >= cbSize))
275 {
276 rc = vdIfIoIntFileSetAllocationSize(pImage->pIfIo, pImage->pStorage, cbSize, 0 /* fFlags */,
277 pIfProgress, uPercentStart, uPercentSpan);
278 if (RT_SUCCESS(rc))
279 {
280 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 98 / 100);
281
282 pImage->cbSize = cbSize;
283 rc = rawFlushImage(pImage);
284 }
285 }
286 else
287 rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
288 }
289 else
290 {
291 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbSize);
292 if (RT_SUCCESS(rc))
293 pImage->cbSize = cbSize;
294 }
295 }
296 else
297 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename);
298 }
299 else
300 rc = vdIfError(pImage->pIfError, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename);
301
302 if (RT_SUCCESS(rc))
303 {
304 PVDREGIONDESC pRegion = &pImage->RegionList.aRegions[0];
305 pImage->RegionList.fFlags = 0;
306 pImage->RegionList.cRegions = 1;
307
308 pRegion->offRegion = 0; /* Disk start. */
309 pRegion->cbBlock = pImage->cbSector;
310 pRegion->enmDataForm = VDREGIONDATAFORM_RAW;
311 pRegion->enmMetadataForm = VDREGIONMETADATAFORM_NONE;
312 pRegion->cbData = pImage->cbSector;
313 pRegion->cbMetadata = 0;
314 pRegion->cRegionBlocksOrBytes = pImage->cbSize;
315
316 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan);
317 }
318
319 if (RT_FAILURE(rc))
320 rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
321 return rc;
322}
323
324/**
325 * Worker for rawProbe that checks if the file looks like it contains an ISO
326 * 9660 or UDF descriptor sequence at the expected offset.
327 *
328 * Caller already checked if the size is suitable for ISOs.
329 *
330 * @returns IPRT status code. Success if detected ISO 9660 or UDF, failure if
331 * not.
332 *
333 * @note Code is a modified version of rtFsIsoVolTryInit() IPRT (isovfs.cpp).
334 */
335static int rawProbeIsIso9660OrUdf(PVDINTERFACEIOINT pIfIo, PVDIOSTORAGE pStorage)
336{
337 PRTERRINFO pErrInfo = NULL;
338 const uint32_t cbSector = _2K;
339
340 union
341 {
342 uint8_t ab[_2K];
343 ISO9660VOLDESCHDR VolDescHdr;
344 } Buf;
345 Assert(cbSector <= sizeof(Buf));
346 RT_ZERO(Buf);
347
348 uint8_t uUdfLevel = 0;
349 uint64_t offUdfBootVolDesc = UINT64_MAX;
350
351 uint32_t cPrimaryVolDescs = 0;
352 uint32_t cSupplementaryVolDescs = 0;
353 uint32_t cBootRecordVolDescs = 0;
354 uint32_t offVolDesc = 16 * cbSector;
355 enum
356 {
357 kStateStart = 0,
358 kStateNoSeq,
359 kStateCdSeq,
360 kStateUdfSeq
361 } enmState = kStateStart;
362 for (uint32_t iVolDesc = 0; ; iVolDesc++, offVolDesc += cbSector)
363 {
364 if (iVolDesc > 32)
365 return RTERRINFO_LOG_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "More than 32 volume descriptors, doesn't seem right...");
366
367 /* Read the next one and check the signature. */
368 int rc = vdIfIoIntFileReadSync(pIfIo, pStorage, offVolDesc, &Buf, cbSector);
369 if (RT_FAILURE(rc))
370 return RTERRINFO_LOG_SET_F(pErrInfo, rc, "Unable to read volume descriptor #%u", iVolDesc);
371
372#define MATCH_STD_ID(a_achStdId1, a_szStdId2) \
373 ( (a_achStdId1)[0] == (a_szStdId2)[0] \
374 && (a_achStdId1)[1] == (a_szStdId2)[1] \
375 && (a_achStdId1)[2] == (a_szStdId2)[2] \
376 && (a_achStdId1)[3] == (a_szStdId2)[3] \
377 && (a_achStdId1)[4] == (a_szStdId2)[4] )
378#define MATCH_HDR(a_pStd, a_bType2, a_szStdId2, a_bVer2) \
379 ( MATCH_STD_ID((a_pStd)->achStdId, a_szStdId2) \
380 && (a_pStd)->bDescType == (a_bType2) \
381 && (a_pStd)->bDescVersion == (a_bVer2) )
382
383 /*
384 * ISO 9660 ("CD001").
385 */
386 if ( ( enmState == kStateStart
387 || enmState == kStateCdSeq
388 || enmState == kStateNoSeq)
389 && MATCH_STD_ID(Buf.VolDescHdr.achStdId, ISO9660VOLDESC_STD_ID) )
390 {
391 enmState = kStateCdSeq;
392
393 /* Do type specific handling. */
394 Log(("RAW/ISO9660: volume desc #%u: type=%#x\n", iVolDesc, Buf.VolDescHdr.bDescType));
395 if (Buf.VolDescHdr.bDescType == ISO9660VOLDESC_TYPE_PRIMARY)
396 {
397 cPrimaryVolDescs++;
398 if (Buf.VolDescHdr.bDescVersion != ISO9660PRIMARYVOLDESC_VERSION)
399 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
400 "Unsupported primary volume descriptor version: %#x", Buf.VolDescHdr.bDescVersion);
401 if (cPrimaryVolDescs == 1)
402 { /*rc = rtFsIsoVolHandlePrimaryVolDesc(pThis, &Buf.PrimaryVolDesc, offVolDesc, &RootDir, &offRootDirRec, pErrInfo);*/ }
403 else if (cPrimaryVolDescs == 2)
404 Log(("RAW/ISO9660: ignoring 2nd primary descriptor\n")); /* so we can read the w2k3 ifs kit */
405 else
406 return RTERRINFO_LOG_SET(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT, "More than one primary volume descriptor");
407 }
408 else if (Buf.VolDescHdr.bDescType == ISO9660VOLDESC_TYPE_SUPPLEMENTARY)
409 {
410 cSupplementaryVolDescs++;
411 if (Buf.VolDescHdr.bDescVersion != ISO9660SUPVOLDESC_VERSION)
412 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
413 "Unsupported supplemental volume descriptor version: %#x", Buf.VolDescHdr.bDescVersion);
414 /*rc = rtFsIsoVolHandleSupplementaryVolDesc(pThis, &Buf.SupVolDesc, offVolDesc, &bJolietUcs2Level, &JolietRootDir,
415 &offJolietRootDirRec, pErrInfo);*/
416 }
417 else if (Buf.VolDescHdr.bDescType == ISO9660VOLDESC_TYPE_BOOT_RECORD)
418 {
419 cBootRecordVolDescs++;
420 }
421 else if (Buf.VolDescHdr.bDescType == ISO9660VOLDESC_TYPE_TERMINATOR)
422 {
423 if (!cPrimaryVolDescs)
424 return RTERRINFO_LOG_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "No primary volume descriptor");
425 enmState = kStateNoSeq;
426 }
427 else
428 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
429 "Unknown volume descriptor: %#x", Buf.VolDescHdr.bDescType);
430 }
431 /*
432 * UDF volume recognition sequence (VRS).
433 */
434 else if ( ( enmState == kStateNoSeq
435 || enmState == kStateStart)
436 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_BEGIN, UDF_EXT_VOL_DESC_VERSION) )
437 {
438 if (uUdfLevel == 0)
439 enmState = kStateUdfSeq;
440 else
441 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "Only one BEA01 sequence is supported");
442 }
443 else if ( enmState == kStateUdfSeq
444 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_NSR_02, UDF_EXT_VOL_DESC_VERSION) )
445 uUdfLevel = 2;
446 else if ( enmState == kStateUdfSeq
447 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_NSR_03, UDF_EXT_VOL_DESC_VERSION) )
448 uUdfLevel = 3;
449 else if ( enmState == kStateUdfSeq
450 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_BOOT, UDF_EXT_VOL_DESC_VERSION) )
451 {
452 if (offUdfBootVolDesc == UINT64_MAX)
453 offUdfBootVolDesc = iVolDesc * cbSector;
454 else
455 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "Only one BOOT2 descriptor is supported");
456 }
457 else if ( enmState == kStateUdfSeq
458 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_TERM, UDF_EXT_VOL_DESC_VERSION) )
459 {
460 if (uUdfLevel != 0)
461 enmState = kStateNoSeq;
462 else
463 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "Found BEA01 & TEA01, but no NSR02 or NSR03 descriptors");
464 }
465 /*
466 * Unknown, probably the end.
467 */
468 else if (enmState == kStateNoSeq)
469 break;
470 else if (enmState == kStateStart)
471 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNKNOWN_FORMAT,
472 "Not ISO? Unable to recognize volume descriptor signature: %.5Rhxs", Buf.VolDescHdr.achStdId);
473 else if (enmState == kStateCdSeq)
474 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
475 "Missing ISO 9660 terminator volume descriptor? (Found %.5Rhxs)", Buf.VolDescHdr.achStdId);
476 else if (enmState == kStateUdfSeq)
477 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
478 "Missing UDF terminator volume descriptor? (Found %.5Rhxs)", Buf.VolDescHdr.achStdId);
479 else
480 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNKNOWN_FORMAT,
481 "Unknown volume descriptor signature found at sector %u: %.5Rhxs",
482 16 + iVolDesc, Buf.VolDescHdr.achStdId);
483 }
484
485 return VINF_SUCCESS;
486}
487
488/**
489 * Checks the given extension array for the given suffix and type.
490 *
491 * @returns true if found in the list, false if not.
492 * @param paExtensions The extension array to check against.
493 * @param pszSuffix The suffix to look for. Can be NULL.
494 * @param enmType The image type to look for.
495 */
496static bool rawProbeContainsExtension(const VDFILEEXTENSION *paExtensions, const char *pszSuffix, VDTYPE enmType)
497{
498 if (pszSuffix)
499 {
500 if (*pszSuffix == '.')
501 pszSuffix++;
502 if (*pszSuffix != '\0')
503 {
504 for (size_t i = 0;; i++)
505 {
506 if (!paExtensions[i].pszExtension)
507 break;
508 if ( paExtensions[i].enmType == enmType
509 && RTStrICmpAscii(paExtensions[i].pszExtension, pszSuffix) == 0)
510 return true;
511 }
512 }
513 }
514 return false;
515}
516
517
518/** @copydoc VDIMAGEBACKEND::pfnProbe */
519static DECLCALLBACK(int) rawProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
520 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
521{
522 RT_NOREF(pVDIfsDisk, enmDesiredType);
523 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
524 PVDIOSTORAGE pStorage = NULL;
525 PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage);
526
527 AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
528 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
529 AssertReturn(*pszFilename != '\0', VERR_INVALID_PARAMETER);
530
531 /*
532 * Open the file and read the footer.
533 */
534 int rc = vdIfIoIntFileOpen(pIfIo, pszFilename,
535 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
536 false /* fCreate */),
537 &pStorage);
538 if (RT_SUCCESS(rc))
539 {
540 uint64_t cbFile;
541 rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile);
542 if (RT_SUCCESS(rc))
543 {
544 /*
545 * Detecting raw ISO and floppy images and keeping them apart isn't all
546 * that simple.
547 *
548 * - Both must be a multiple of their sector sizes, though
549 * that means that any ISO can also be a floppy, since 2048 is 512 * 4.
550 * - The ISO images must be 32KB and floppies are generally not larger
551 * than 2.88MB, but that leaves quite a bit of size overlap,
552 *
553 * So, the size cannot conclusively say whether something is one or the other.
554 *
555 * - The content of a normal ISO image is detectable, but not all ISO
556 * images need to follow that spec to work in a DVD ROM drive.
557 * - It is common for ISO images to start like a floppy with a boot sector
558 * at the very start of the image.
559 * - Floppies doesn't need to contain a DOS-style boot sector, it depends
560 * on the system it is formatted and/or intended for.
561 *
562 * So, the content cannot conclusively determine the type either.
563 *
564 * However, there are a number of cases, especially for ISOs, where we can
565 * say we a deal of confidence that something is an ISO image.
566 */
567 const char * const pszSuffix = RTPathSuffix(pszFilename);
568
569 /*
570 * Start by checking for sure signs of an ISO 9660 / UDF image.
571 */
572 rc = VERR_VD_RAW_INVALID_HEADER;
573 if ( (enmDesiredType == VDTYPE_INVALID || enmDesiredType == VDTYPE_OPTICAL_DISC)
574 && (cbFile % 2048) == 0
575 && cbFile > 32768)
576 {
577 int rc2 = rawProbeIsIso9660OrUdf(pIfIo, pStorage);
578 if (RT_SUCCESS(rc2))
579 {
580 /* *puScore = VDPROBE_SCORE_HIGH; */
581 *penmType = VDTYPE_OPTICAL_DISC;
582 rc = VINF_SUCCESS;
583 }
584 /* If that didn't work out, check by extension (the old way): */
585 else if (rawProbeContainsExtension(s_aRawFileExtensions, pszSuffix, VDTYPE_OPTICAL_DISC))
586 {
587 /* *puScore = VDPROBE_SCORE_LOW; */
588 *penmType = VDTYPE_OPTICAL_DISC;
589 rc = VINF_SUCCESS;
590 }
591 }
592
593 /*
594 * We could do something similar for floppies, i.e. check for a
595 * DOS'ish boot sector and thereby get a good match on most of the
596 * relevant floppy images out there.
597 */
598 if ( RT_FAILURE(rc)
599 && (enmDesiredType == VDTYPE_INVALID || enmDesiredType == VDTYPE_FLOPPY)
600 && (cbFile % 512) == 0
601 && cbFile >= 512
602 && cbFile <= RAW_MAX_FLOPPY_IMG_SIZE)
603 {
604 /** @todo check if the content is DOSish. */
605 if (false)
606 {
607 /* *puScore = VDPROBE_SCORE_HIGH; */
608 *penmType = VDTYPE_FLOPPY;
609 rc = VINF_SUCCESS;
610 }
611 else if (rawProbeContainsExtension(s_aRawFileExtensions, pszSuffix, VDTYPE_FLOPPY))
612 {
613 /* *puScore = VDPROBE_SCORE_LOW; */
614 *penmType = VDTYPE_FLOPPY;
615 rc = VINF_SUCCESS;
616 }
617 }
618
619 /*
620 * No luck? Go exclusively by extension like we've done since
621 * for ever and complain about the size if it doesn't fit expectations.
622 * We can get here if the desired type doesn't match the extension and such.
623 */
624 if (RT_FAILURE(rc))
625 {
626 if (rawProbeContainsExtension(s_aRawFileExtensions, pszSuffix, VDTYPE_OPTICAL_DISC))
627 {
628 if (cbFile % 2048)
629 rc = VERR_VD_RAW_SIZE_MODULO_2048;
630 else if (cbFile <= 32768)
631 rc = VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL;
632 else
633 {
634 Assert(enmDesiredType != VDTYPE_OPTICAL_DISC);
635 *penmType = VDTYPE_OPTICAL_DISC;
636 rc = VINF_SUCCESS;
637 }
638 }
639 else if (rawProbeContainsExtension(s_aRawFileExtensions, pszSuffix, VDTYPE_FLOPPY))
640 {
641 if (cbFile % 512)
642 rc = VERR_VD_RAW_SIZE_MODULO_512;
643 else if (cbFile > RAW_MAX_FLOPPY_IMG_SIZE)
644 rc = VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG;
645 else
646 {
647 Assert(cbFile == 0 || enmDesiredType != VDTYPE_FLOPPY);
648 *penmType = VDTYPE_FLOPPY;
649 rc = VINF_SUCCESS;
650 }
651 }
652 else
653 rc = VERR_VD_RAW_INVALID_HEADER;
654 }
655 }
656 else
657 rc = VERR_VD_RAW_INVALID_HEADER;
658 }
659
660 if (pStorage)
661 vdIfIoIntFileClose(pIfIo, pStorage);
662
663 LogFlowFunc(("returns %Rrc\n", rc));
664 return rc;
665}
666
667/** @copydoc VDIMAGEBACKEND::pfnOpen */
668static DECLCALLBACK(int) rawOpen(const char *pszFilename, unsigned uOpenFlags,
669 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
670 VDTYPE enmType, void **ppBackendData)
671{
672 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n",
673 pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData));
674 int rc;
675 PRAWIMAGE pImage;
676
677 /* Check open flags. All valid flags are supported. */
678 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
679 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
680 AssertReturn(*pszFilename != '\0', VERR_INVALID_PARAMETER);
681
682 pImage = (PRAWIMAGE)RTMemAllocZ(RT_UOFFSETOF(RAWIMAGE, RegionList.aRegions[1]));
683 if (RT_LIKELY(pImage))
684 {
685 pImage->pszFilename = pszFilename;
686 pImage->pStorage = NULL;
687 pImage->pVDIfsDisk = pVDIfsDisk;
688 pImage->pVDIfsImage = pVDIfsImage;
689
690 if (enmType == VDTYPE_OPTICAL_DISC)
691 pImage->cbSector = 2048;
692 else
693 pImage->cbSector = 512;
694
695 rc = rawOpenImage(pImage, uOpenFlags);
696 if (RT_SUCCESS(rc))
697 *ppBackendData = pImage;
698 else
699 RTMemFree(pImage);
700 }
701 else
702 rc = VERR_NO_MEMORY;
703
704 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
705 return rc;
706}
707
708/** @copydoc VDIMAGEBACKEND::pfnCreate */
709static DECLCALLBACK(int) rawCreate(const char *pszFilename, uint64_t cbSize,
710 unsigned uImageFlags, const char *pszComment,
711 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
712 PCRTUUID pUuid, unsigned uOpenFlags,
713 unsigned uPercentStart, unsigned uPercentSpan,
714 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
715 PVDINTERFACE pVDIfsOperation, VDTYPE enmType,
716 void **ppBackendData)
717{
718 RT_NOREF1(pUuid);
719 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",
720 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, enmType, ppBackendData));
721
722 /* Check the VD container type. Yes, hard disk must be allowed, otherwise
723 * various tools using this backend for hard disk images will fail. */
724 if (enmType != VDTYPE_HDD && enmType != VDTYPE_OPTICAL_DISC && enmType != VDTYPE_FLOPPY)
725 return VERR_VD_INVALID_TYPE;
726
727 int rc = VINF_SUCCESS;
728 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);
729
730 /* Check arguments. */
731 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
732 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
733 AssertReturn(*pszFilename != '\0', VERR_INVALID_PARAMETER);
734 AssertPtrReturn(pPCHSGeometry, VERR_INVALID_POINTER);
735 AssertPtrReturn(pLCHSGeometry, VERR_INVALID_POINTER);
736
737 PRAWIMAGE pImage = (PRAWIMAGE)RTMemAllocZ(RT_UOFFSETOF(RAWIMAGE, RegionList.aRegions[1]));
738 if (RT_LIKELY(pImage))
739 {
740 pImage->pszFilename = pszFilename;
741 pImage->pStorage = NULL;
742 pImage->pVDIfsDisk = pVDIfsDisk;
743 pImage->pVDIfsImage = pVDIfsImage;
744
745 rc = rawCreateImage(pImage, cbSize, uImageFlags, pszComment,
746 pPCHSGeometry, pLCHSGeometry, uOpenFlags,
747 pIfProgress, uPercentStart, uPercentSpan);
748 if (RT_SUCCESS(rc))
749 {
750 /* So far the image is opened in read/write mode. Make sure the
751 * image is opened in read-only mode if the caller requested that. */
752 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
753 {
754 rawFreeImage(pImage, false);
755 rc = rawOpenImage(pImage, uOpenFlags);
756 }
757
758 if (RT_SUCCESS(rc))
759 *ppBackendData = pImage;
760 }
761
762 if (RT_FAILURE(rc))
763 RTMemFree(pImage);
764 }
765 else
766 rc = VERR_NO_MEMORY;
767
768 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
769 return rc;
770}
771
772/** @copydoc VDIMAGEBACKEND::pfnRename */
773static DECLCALLBACK(int) rawRename(void *pBackendData, const char *pszFilename)
774{
775 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
776 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
777
778 AssertReturn((pImage && pszFilename && *pszFilename), VERR_INVALID_PARAMETER);
779
780 /* Close the image. */
781 int rc = rawFreeImage(pImage, false);
782 if (RT_SUCCESS(rc))
783 {
784 /* Rename the file. */
785 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0);
786 if (RT_SUCCESS(rc))
787 {
788 /* Update pImage with the new information. */
789 pImage->pszFilename = pszFilename;
790
791 /* Open the old image with new name. */
792 rc = rawOpenImage(pImage, pImage->uOpenFlags);
793 }
794 else
795 {
796 /* The move failed, try to reopen the original image. */
797 int rc2 = rawOpenImage(pImage, pImage->uOpenFlags);
798 if (RT_FAILURE(rc2))
799 rc = rc2;
800 }
801 }
802
803 LogFlowFunc(("returns %Rrc\n", rc));
804 return rc;
805}
806
807/** @copydoc VDIMAGEBACKEND::pfnClose */
808static DECLCALLBACK(int) rawClose(void *pBackendData, bool fDelete)
809{
810 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
811 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
812 int rc = rawFreeImage(pImage, fDelete);
813 RTMemFree(pImage);
814
815 LogFlowFunc(("returns %Rrc\n", rc));
816 return rc;
817}
818
819/** @copydoc VDIMAGEBACKEND::pfnRead */
820static DECLCALLBACK(int) rawRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
821 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
822{
823 int rc = VINF_SUCCESS;
824 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
825
826 /* For sequential access do not allow to go back. */
827 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
828 && uOffset < pImage->offAccess)
829 {
830 *pcbActuallyRead = 0;
831 return VERR_INVALID_PARAMETER;
832 }
833
834 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,
835 pIoCtx, cbToRead);
836 if (RT_SUCCESS(rc))
837 {
838 *pcbActuallyRead = cbToRead;
839 pImage->offAccess = uOffset + cbToRead;
840 }
841
842 return rc;
843}
844
845/** @copydoc VDIMAGEBACKEND::pfnWrite */
846static DECLCALLBACK(int) rawWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
847 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
848 size_t *pcbPostRead, unsigned fWrite)
849{
850 RT_NOREF1(fWrite);
851 int rc = VINF_SUCCESS;
852 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
853
854 /* For sequential access do not allow to go back. */
855 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
856 && uOffset < pImage->offAccess)
857 {
858 *pcbWriteProcess = 0;
859 *pcbPostRead = 0;
860 *pcbPreRead = 0;
861 return VERR_INVALID_PARAMETER;
862 }
863
864 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, uOffset,
865 pIoCtx, cbToWrite, NULL, NULL);
866 if (RT_SUCCESS(rc))
867 {
868 *pcbWriteProcess = cbToWrite;
869 *pcbPostRead = 0;
870 *pcbPreRead = 0;
871 pImage->offAccess = uOffset + cbToWrite;
872 }
873
874 return rc;
875}
876
877/** @copydoc VDIMAGEBACKEND::pfnFlush */
878static DECLCALLBACK(int) rawFlush(void *pBackendData, PVDIOCTX pIoCtx)
879{
880 int rc = VINF_SUCCESS;
881 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
882
883 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
884 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx,
885 NULL, NULL);
886
887 return rc;
888}
889
890/** @copydoc VDIMAGEBACKEND::pfnGetVersion */
891static DECLCALLBACK(unsigned) rawGetVersion(void *pBackendData)
892{
893 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
894 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
895
896 AssertPtrReturn(pImage, 0);
897
898 return 1;
899}
900
901/** @copydoc VDIMAGEBACKEND::pfnGetFileSize */
902static DECLCALLBACK(uint64_t) rawGetFileSize(void *pBackendData)
903{
904 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
905 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
906
907 AssertPtrReturn(pImage, 0);
908
909 uint64_t cbFile = 0;
910 if (pImage->pStorage)
911 {
912 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
913 if (RT_FAILURE(rc))
914 cbFile = 0; /* Make sure it is 0 */
915 }
916
917 LogFlowFunc(("returns %lld\n", cbFile));
918 return cbFile;
919}
920
921/** @copydoc VDIMAGEBACKEND::pfnGetPCHSGeometry */
922static DECLCALLBACK(int) rawGetPCHSGeometry(void *pBackendData,
923 PVDGEOMETRY pPCHSGeometry)
924{
925 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
926 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
927 int rc = VINF_SUCCESS;
928
929 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
930
931 if (pImage->PCHSGeometry.cCylinders)
932 *pPCHSGeometry = pImage->PCHSGeometry;
933 else
934 rc = VERR_VD_GEOMETRY_NOT_SET;
935
936 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
937 return rc;
938}
939
940/** @copydoc VDIMAGEBACKEND::pfnSetPCHSGeometry */
941static DECLCALLBACK(int) rawSetPCHSGeometry(void *pBackendData,
942 PCVDGEOMETRY pPCHSGeometry)
943{
944 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n",
945 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
946 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
947 int rc = VINF_SUCCESS;
948
949 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
950
951 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
952 rc = VERR_VD_IMAGE_READ_ONLY;
953 else
954 pImage->PCHSGeometry = *pPCHSGeometry;
955
956 LogFlowFunc(("returns %Rrc\n", rc));
957 return rc;
958}
959
960/** @copydoc VDIMAGEBACKEND::pfnGetLCHSGeometry */
961static DECLCALLBACK(int) rawGetLCHSGeometry(void *pBackendData,
962 PVDGEOMETRY pLCHSGeometry)
963{
964 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
965 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
966 int rc = VINF_SUCCESS;
967
968 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
969
970 if (pImage->LCHSGeometry.cCylinders)
971 *pLCHSGeometry = pImage->LCHSGeometry;
972 else
973 rc = VERR_VD_GEOMETRY_NOT_SET;
974
975 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
976 return rc;
977}
978
979/** @copydoc VDIMAGEBACKEND::pfnSetLCHSGeometry */
980static DECLCALLBACK(int) rawSetLCHSGeometry(void *pBackendData,
981 PCVDGEOMETRY pLCHSGeometry)
982{
983 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n",
984 pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
985 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
986 int rc = VINF_SUCCESS;
987
988 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
989
990 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
991 rc = VERR_VD_IMAGE_READ_ONLY;
992 else
993 pImage->LCHSGeometry = *pLCHSGeometry;
994
995 LogFlowFunc(("returns %Rrc\n", rc));
996 return rc;
997}
998
999/** @copydoc VDIMAGEBACKEND::pfnQueryRegions */
1000static DECLCALLBACK(int) rawQueryRegions(void *pBackendData, PCVDREGIONLIST *ppRegionList)
1001{
1002 LogFlowFunc(("pBackendData=%#p ppRegionList=%#p\n", pBackendData, ppRegionList));
1003 PRAWIMAGE pThis = (PRAWIMAGE)pBackendData;
1004
1005 AssertPtrReturn(pThis, VERR_VD_NOT_OPENED);
1006
1007 *ppRegionList = &pThis->RegionList;
1008 LogFlowFunc(("returns %Rrc\n", VINF_SUCCESS));
1009 return VINF_SUCCESS;
1010}
1011
1012/** @copydoc VDIMAGEBACKEND::pfnRegionListRelease */
1013static DECLCALLBACK(void) rawRegionListRelease(void *pBackendData, PCVDREGIONLIST pRegionList)
1014{
1015 RT_NOREF1(pRegionList);
1016 LogFlowFunc(("pBackendData=%#p pRegionList=%#p\n", pBackendData, pRegionList));
1017 PRAWIMAGE pThis = (PRAWIMAGE)pBackendData;
1018 AssertPtr(pThis); RT_NOREF(pThis);
1019
1020 /* Nothing to do here. */
1021}
1022
1023/** @copydoc VDIMAGEBACKEND::pfnGetImageFlags */
1024static DECLCALLBACK(unsigned) rawGetImageFlags(void *pBackendData)
1025{
1026 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1027 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1028
1029 AssertPtrReturn(pImage, 0);
1030
1031 LogFlowFunc(("returns %#x\n", pImage->uImageFlags));
1032 return pImage->uImageFlags;
1033}
1034
1035/** @copydoc VDIMAGEBACKEND::pfnGetOpenFlags */
1036static DECLCALLBACK(unsigned) rawGetOpenFlags(void *pBackendData)
1037{
1038 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
1039 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1040
1041 AssertPtrReturn(pImage, 0);
1042
1043 LogFlowFunc(("returns %#x\n", pImage->uOpenFlags));
1044 return pImage->uOpenFlags;
1045}
1046
1047/** @copydoc VDIMAGEBACKEND::pfnSetOpenFlags */
1048static DECLCALLBACK(int) rawSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
1049{
1050 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
1051 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1052 int rc = VINF_SUCCESS;
1053
1054 /* Image must be opened and the new flags must be valid. */
1055 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
1056 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
1057 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
1058 rc = VERR_INVALID_PARAMETER;
1059 else
1060 {
1061 /* Implement this operation via reopening the image. */
1062 rc = rawFreeImage(pImage, false);
1063 if (RT_SUCCESS(rc))
1064 rc = rawOpenImage(pImage, uOpenFlags);
1065 }
1066
1067 LogFlowFunc(("returns %Rrc\n", rc));
1068 return rc;
1069}
1070
1071/** @copydoc VDIMAGEBACKEND::pfnGetComment */
1072VD_BACKEND_CALLBACK_GET_COMMENT_DEF_NOT_SUPPORTED(rawGetComment);
1073
1074/** @copydoc VDIMAGEBACKEND::pfnSetComment */
1075VD_BACKEND_CALLBACK_SET_COMMENT_DEF_NOT_SUPPORTED(rawSetComment, PRAWIMAGE);
1076
1077/** @copydoc VDIMAGEBACKEND::pfnGetUuid */
1078VD_BACKEND_CALLBACK_GET_UUID_DEF_NOT_SUPPORTED(rawGetUuid);
1079
1080/** @copydoc VDIMAGEBACKEND::pfnSetUuid */
1081VD_BACKEND_CALLBACK_SET_UUID_DEF_NOT_SUPPORTED(rawSetUuid, PRAWIMAGE);
1082
1083/** @copydoc VDIMAGEBACKEND::pfnGetModificationUuid */
1084VD_BACKEND_CALLBACK_GET_UUID_DEF_NOT_SUPPORTED(rawGetModificationUuid);
1085
1086/** @copydoc VDIMAGEBACKEND::pfnSetModificationUuid */
1087VD_BACKEND_CALLBACK_SET_UUID_DEF_NOT_SUPPORTED(rawSetModificationUuid, PRAWIMAGE);
1088
1089/** @copydoc VDIMAGEBACKEND::pfnGetParentUuid */
1090VD_BACKEND_CALLBACK_GET_UUID_DEF_NOT_SUPPORTED(rawGetParentUuid);
1091
1092/** @copydoc VDIMAGEBACKEND::pfnSetParentUuid */
1093VD_BACKEND_CALLBACK_SET_UUID_DEF_NOT_SUPPORTED(rawSetParentUuid, PRAWIMAGE);
1094
1095/** @copydoc VDIMAGEBACKEND::pfnGetParentModificationUuid */
1096VD_BACKEND_CALLBACK_GET_UUID_DEF_NOT_SUPPORTED(rawGetParentModificationUuid);
1097
1098/** @copydoc VDIMAGEBACKEND::pfnSetParentModificationUuid */
1099VD_BACKEND_CALLBACK_SET_UUID_DEF_NOT_SUPPORTED(rawSetParentModificationUuid, PRAWIMAGE);
1100
1101/** @copydoc VDIMAGEBACKEND::pfnDump */
1102static DECLCALLBACK(void) rawDump(void *pBackendData)
1103{
1104 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1105
1106 AssertPtrReturnVoid(pImage);
1107 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
1108 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
1109 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
1110 pImage->cbSize / 512);
1111}
1112
1113
1114
1115const VDIMAGEBACKEND g_RawBackend =
1116{
1117 /* u32Version */
1118 VD_IMGBACKEND_VERSION,
1119 /* pszBackendName */
1120 "RAW",
1121 /* uBackendCaps */
1122 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
1123 /* paFileExtensions */
1124 s_aRawFileExtensions,
1125 /* paConfigInfo */
1126 NULL,
1127 /* pfnProbe */
1128 rawProbe,
1129 /* pfnOpen */
1130 rawOpen,
1131 /* pfnCreate */
1132 rawCreate,
1133 /* pfnRename */
1134 rawRename,
1135 /* pfnClose */
1136 rawClose,
1137 /* pfnRead */
1138 rawRead,
1139 /* pfnWrite */
1140 rawWrite,
1141 /* pfnFlush */
1142 rawFlush,
1143 /* pfnDiscard */
1144 NULL,
1145 /* pfnGetVersion */
1146 rawGetVersion,
1147 /* pfnGetFileSize */
1148 rawGetFileSize,
1149 /* pfnGetPCHSGeometry */
1150 rawGetPCHSGeometry,
1151 /* pfnSetPCHSGeometry */
1152 rawSetPCHSGeometry,
1153 /* pfnGetLCHSGeometry */
1154 rawGetLCHSGeometry,
1155 /* pfnSetLCHSGeometry */
1156 rawSetLCHSGeometry,
1157 /* pfnQueryRegions */
1158 rawQueryRegions,
1159 /* pfnRegionListRelease */
1160 rawRegionListRelease,
1161 /* pfnGetImageFlags */
1162 rawGetImageFlags,
1163 /* pfnGetOpenFlags */
1164 rawGetOpenFlags,
1165 /* pfnSetOpenFlags */
1166 rawSetOpenFlags,
1167 /* pfnGetComment */
1168 rawGetComment,
1169 /* pfnSetComment */
1170 rawSetComment,
1171 /* pfnGetUuid */
1172 rawGetUuid,
1173 /* pfnSetUuid */
1174 rawSetUuid,
1175 /* pfnGetModificationUuid */
1176 rawGetModificationUuid,
1177 /* pfnSetModificationUuid */
1178 rawSetModificationUuid,
1179 /* pfnGetParentUuid */
1180 rawGetParentUuid,
1181 /* pfnSetParentUuid */
1182 rawSetParentUuid,
1183 /* pfnGetParentModificationUuid */
1184 rawGetParentModificationUuid,
1185 /* pfnSetParentModificationUuid */
1186 rawSetParentModificationUuid,
1187 /* pfnDump */
1188 rawDump,
1189 /* pfnGetTimestamp */
1190 NULL,
1191 /* pfnGetParentTimestamp */
1192 NULL,
1193 /* pfnSetParentTimestamp */
1194 NULL,
1195 /* pfnGetParentFilename */
1196 NULL,
1197 /* pfnSetParentFilename */
1198 NULL,
1199 /* pfnComposeLocation */
1200 genericFileComposeLocation,
1201 /* pfnComposeName */
1202 genericFileComposeName,
1203 /* pfnCompact */
1204 NULL,
1205 /* pfnResize */
1206 NULL,
1207 /* pfnRepair */
1208 NULL,
1209 /* pfnTraverseMetadata */
1210 NULL,
1211 /* u32VersionEnd */
1212 VD_IMGBACKEND_VERSION
1213};
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