VirtualBox

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

Last change on this file since 63803 was 63802, checked in by vboxsync, 8 years ago

Storage/VD: Rename pfnCheckIfValid to pfnProbe as it is shorter and easier to spell

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