VirtualBox

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

最後變更 在這個檔案從57213是 57213,由 vboxsync 提交於 10 年 前

split VERR_VD_RAW_INVALID_HEADER a bit further to have better error messages under certain conditions

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette