VirtualBox

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

Last change on this file since 64226 was 63905, checked in by vboxsync, 8 years ago

Storage/VD: Add proper versioning of the backend structures instead of just relying on the structure size to make changing callback signatures possible in the future and still being able to reject incompatible plugins

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.0 KB
Line 
1/* $Id: RAW.cpp 63905 2016-09-20 08:31:05Z 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, uPercentStart, uPercentSpan);
259 if (RT_SUCCESS(rc))
260 {
261 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 98 / 100);
262
263 pImage->cbSize = cbSize;
264 rc = rawFlushImage(pImage);
265 }
266 }
267 else
268 rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
269 }
270 }
271 else
272 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename);
273 }
274 else
275 rc = vdIfError(pImage->pIfError, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename);
276
277 if (RT_SUCCESS(rc))
278 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan);
279
280 if (RT_FAILURE(rc))
281 rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
282 return rc;
283}
284
285
286/** @copydoc VDIMAGEBACKEND::pfnProbe */
287static DECLCALLBACK(int) rawProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
288 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
289{
290 RT_NOREF1(pVDIfsDisk);
291 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
292 PVDIOSTORAGE pStorage = NULL;
293 PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage);
294
295 AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
296 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
297
298 /*
299 * Open the file and read the footer.
300 */
301 int rc = vdIfIoIntFileOpen(pIfIo, pszFilename,
302 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
303 false /* fCreate */),
304 &pStorage);
305 if (RT_SUCCESS(rc))
306 {
307 uint64_t cbFile;
308 const char *pszSuffix = RTPathSuffix(pszFilename);
309 rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile);
310
311 /* Try to guess the image type based on the extension. */
312 if ( RT_SUCCESS(rc)
313 && pszSuffix)
314 {
315 if ( !RTStrICmp(pszSuffix, ".iso")
316 || !RTStrICmp(pszSuffix, ".cdr")) /* DVD images. */
317 {
318 /* Note that there are ISO images smaller than 1 MB; it is impossible to distinguish
319 * between raw floppy and CD images based on their size (and cannot be reliably done
320 * based on contents, either).
321 */
322 if (cbFile % 2048)
323 rc = VERR_VD_RAW_SIZE_MODULO_2048;
324 else if (cbFile <= 32768)
325 rc = VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL;
326 else
327 {
328 *penmType = VDTYPE_DVD;
329 rc = VINF_SUCCESS;
330 }
331 }
332 else if ( !RTStrICmp(pszSuffix, ".img")
333 || !RTStrICmp(pszSuffix, ".ima")
334 || !RTStrICmp(pszSuffix, ".dsk")
335 || !RTStrICmp(pszSuffix, ".flp")
336 || !RTStrICmp(pszSuffix, ".vfd")) /* Floppy images */
337 {
338 if (cbFile % 512)
339 rc = VERR_VD_RAW_SIZE_MODULO_512;
340 else if (cbFile > RAW_MAX_FLOPPY_IMG_SIZE)
341 rc = VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG;
342 else
343 {
344 *penmType = VDTYPE_FLOPPY;
345 rc = VINF_SUCCESS;
346 }
347 }
348 else
349 rc = VERR_VD_RAW_INVALID_HEADER;
350 }
351 else
352 rc = VERR_VD_RAW_INVALID_HEADER;
353 }
354
355 if (pStorage)
356 vdIfIoIntFileClose(pIfIo, pStorage);
357
358 LogFlowFunc(("returns %Rrc\n", rc));
359 return rc;
360}
361
362/** @copydoc VDIMAGEBACKEND::pfnOpen */
363static DECLCALLBACK(int) rawOpen(const char *pszFilename, unsigned uOpenFlags,
364 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
365 VDTYPE enmType, void **ppBackendData)
366{
367 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n",
368 pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData));
369 int rc;
370 PRAWIMAGE pImage;
371
372 NOREF(enmType); /**< @todo r=klaus make use of the type info. */
373
374 /* Check open flags. All valid flags are supported. */
375 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
376 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
377
378 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
379 if (RT_LIKELY(pImage))
380 {
381 pImage->pszFilename = pszFilename;
382 pImage->pStorage = NULL;
383 pImage->pVDIfsDisk = pVDIfsDisk;
384 pImage->pVDIfsImage = pVDIfsImage;
385
386 rc = rawOpenImage(pImage, uOpenFlags);
387 if (RT_SUCCESS(rc))
388 {
389 if (enmType == VDTYPE_DVD)
390 pImage->cbSector = 2048;
391 else
392 pImage->cbSector = 512;
393 *ppBackendData = pImage;
394 }
395 else
396 RTMemFree(pImage);
397 }
398 else
399 rc = VERR_NO_MEMORY;
400
401 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
402 return rc;
403}
404
405/** @copydoc VDIMAGEBACKEND::pfnCreate */
406static DECLCALLBACK(int) rawCreate(const char *pszFilename, uint64_t cbSize,
407 unsigned uImageFlags, const char *pszComment,
408 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
409 PCRTUUID pUuid, unsigned uOpenFlags,
410 unsigned uPercentStart, unsigned uPercentSpan,
411 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
412 PVDINTERFACE pVDIfsOperation, VDTYPE enmType,
413 void **ppBackendData)
414{
415 RT_NOREF1(pUuid);
416 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",
417 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, enmType, ppBackendData));
418
419 /* Check the VD container type. Yes, hard disk must be allowed, otherwise
420 * various tools using this backend for hard disk images will fail. */
421 if (enmType != VDTYPE_HDD && enmType != VDTYPE_DVD && enmType != VDTYPE_FLOPPY)
422 return VERR_VD_INVALID_TYPE;
423
424 int rc = VINF_SUCCESS;
425 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);
426
427 /* Check arguments. */
428 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
429 AssertReturn( VALID_PTR(pszFilename)
430 && *pszFilename
431 && VALID_PTR(pPCHSGeometry)
432 && VALID_PTR(pLCHSGeometry), VERR_INVALID_PARAMETER);
433
434 PRAWIMAGE pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
435 if (RT_LIKELY(pImage))
436 {
437 pImage->pszFilename = pszFilename;
438 pImage->pStorage = NULL;
439 pImage->pVDIfsDisk = pVDIfsDisk;
440 pImage->pVDIfsImage = pVDIfsImage;
441
442 rc = rawCreateImage(pImage, cbSize, uImageFlags, pszComment,
443 pPCHSGeometry, pLCHSGeometry, uOpenFlags,
444 pIfProgress, uPercentStart, uPercentSpan);
445 if (RT_SUCCESS(rc))
446 {
447 /* So far the image is opened in read/write mode. Make sure the
448 * image is opened in read-only mode if the caller requested that. */
449 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
450 {
451 rawFreeImage(pImage, false);
452 rc = rawOpenImage(pImage, uOpenFlags);
453 }
454
455 if (RT_SUCCESS(rc))
456 *ppBackendData = pImage;
457 }
458
459 if (RT_FAILURE(rc))
460 RTMemFree(pImage);
461 }
462 else
463 rc = VERR_NO_MEMORY;
464
465 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
466 return rc;
467}
468
469/** @copydoc VDIMAGEBACKEND::pfnRename */
470static DECLCALLBACK(int) rawRename(void *pBackendData, const char *pszFilename)
471{
472 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
473 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
474
475 AssertReturn((pImage && pszFilename && *pszFilename), VERR_INVALID_PARAMETER);
476
477 /* Close the image. */
478 int rc = rawFreeImage(pImage, false);
479 if (RT_SUCCESS(rc))
480 {
481 /* Rename the file. */
482 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0);
483 if (RT_SUCCESS(rc))
484 {
485 /* Update pImage with the new information. */
486 pImage->pszFilename = pszFilename;
487
488 /* Open the old image with new name. */
489 rc = rawOpenImage(pImage, pImage->uOpenFlags);
490 }
491 else
492 {
493 /* The move failed, try to reopen the original image. */
494 int rc2 = rawOpenImage(pImage, pImage->uOpenFlags);
495 if (RT_FAILURE(rc2))
496 rc = rc2;
497 }
498 }
499
500 LogFlowFunc(("returns %Rrc\n", rc));
501 return rc;
502}
503
504/** @copydoc VDIMAGEBACKEND::pfnClose */
505static DECLCALLBACK(int) rawClose(void *pBackendData, bool fDelete)
506{
507 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
508 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
509 int rc = rawFreeImage(pImage, fDelete);
510 RTMemFree(pImage);
511
512 LogFlowFunc(("returns %Rrc\n", rc));
513 return rc;
514}
515
516/** @copydoc VDIMAGEBACKEND::pfnRead */
517static DECLCALLBACK(int) rawRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
518 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
519{
520 int rc = VINF_SUCCESS;
521 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
522
523 /* For sequential access do not allow to go back. */
524 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
525 && uOffset < pImage->offAccess)
526 {
527 *pcbActuallyRead = 0;
528 return VERR_INVALID_PARAMETER;
529 }
530
531 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,
532 pIoCtx, cbRead);
533 if (RT_SUCCESS(rc))
534 {
535 *pcbActuallyRead = cbRead;
536 pImage->offAccess = uOffset + cbRead;
537 }
538
539 return rc;
540}
541
542/** @copydoc VDIMAGEBACKEND::pfnWrite */
543static DECLCALLBACK(int) rawWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
544 PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
545 size_t *pcbPostRead, unsigned fWrite)
546{
547 RT_NOREF1(fWrite);
548 int rc = VINF_SUCCESS;
549 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
550
551 /* For sequential access do not allow to go back. */
552 if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
553 && uOffset < pImage->offAccess)
554 {
555 *pcbWriteProcess = 0;
556 *pcbPostRead = 0;
557 *pcbPreRead = 0;
558 return VERR_INVALID_PARAMETER;
559 }
560
561 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, uOffset,
562 pIoCtx, cbWrite, NULL, NULL);
563 if (RT_SUCCESS(rc))
564 {
565 *pcbWriteProcess = cbWrite;
566 *pcbPostRead = 0;
567 *pcbPreRead = 0;
568 pImage->offAccess = uOffset + cbWrite;
569 }
570
571 return rc;
572}
573
574/** @copydoc VDIMAGEBACKEND::pfnFlush */
575static DECLCALLBACK(int) rawFlush(void *pBackendData, PVDIOCTX pIoCtx)
576{
577 int rc = VINF_SUCCESS;
578 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
579
580 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
581 rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx,
582 NULL, NULL);
583
584 return rc;
585}
586
587/** @copydoc VDIMAGEBACKEND::pfnGetVersion */
588static DECLCALLBACK(unsigned) rawGetVersion(void *pBackendData)
589{
590 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
591 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
592
593 AssertPtrReturn(pImage, 0);
594
595 return 1;
596}
597
598/** @copydoc VDIMAGEBACKEND::pfnGetSize */
599static DECLCALLBACK(uint32_t) rawGetSectorSize(void *pBackendData)
600{
601 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
602 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
603 uint32_t cb = 0;
604
605 AssertPtrReturn(pImage, 0);
606
607 if (pImage->pStorage)
608 cb = pImage->cbSector;
609
610 LogFlowFunc(("returns %u\n", cb));
611 return cb;
612}
613
614/** @copydoc VDIMAGEBACKEND::pfnGetSize */
615static DECLCALLBACK(uint64_t) rawGetSize(void *pBackendData)
616{
617 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
618 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
619 uint64_t cb = 0;
620
621 AssertPtrReturn(pImage, 0);
622
623 if (pImage->pStorage)
624 cb = pImage->cbSize;
625
626 LogFlowFunc(("returns %llu\n", cb));
627 return cb;
628}
629
630/** @copydoc VDIMAGEBACKEND::pfnGetFileSize */
631static DECLCALLBACK(uint64_t) rawGetFileSize(void *pBackendData)
632{
633 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
634 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
635
636 AssertPtrReturn(pImage, 0);
637
638 uint64_t cbFile = 0;
639 if (pImage->pStorage)
640 {
641 int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
642 if (RT_FAILURE(rc))
643 cbFile = 0; /* Make sure it is 0 */
644 }
645
646 LogFlowFunc(("returns %lld\n", cbFile));
647 return cbFile;
648}
649
650/** @copydoc VDIMAGEBACKEND::pfnGetPCHSGeometry */
651static DECLCALLBACK(int) rawGetPCHSGeometry(void *pBackendData,
652 PVDGEOMETRY pPCHSGeometry)
653{
654 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
655 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
656 int rc = VINF_SUCCESS;
657
658 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
659
660 if (pImage->PCHSGeometry.cCylinders)
661 *pPCHSGeometry = pImage->PCHSGeometry;
662 else
663 rc = VERR_VD_GEOMETRY_NOT_SET;
664
665 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
666 return rc;
667}
668
669/** @copydoc VDIMAGEBACKEND::pfnSetPCHSGeometry */
670static DECLCALLBACK(int) rawSetPCHSGeometry(void *pBackendData,
671 PCVDGEOMETRY pPCHSGeometry)
672{
673 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n",
674 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
675 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
676 int rc = VINF_SUCCESS;
677
678 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
679
680 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
681 rc = VERR_VD_IMAGE_READ_ONLY;
682 else
683 pImage->PCHSGeometry = *pPCHSGeometry;
684
685 LogFlowFunc(("returns %Rrc\n", rc));
686 return rc;
687}
688
689/** @copydoc VDIMAGEBACKEND::pfnGetLCHSGeometry */
690static DECLCALLBACK(int) rawGetLCHSGeometry(void *pBackendData,
691 PVDGEOMETRY pLCHSGeometry)
692{
693 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
694 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
695 int rc = VINF_SUCCESS;
696
697 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
698
699 if (pImage->LCHSGeometry.cCylinders)
700 *pLCHSGeometry = pImage->LCHSGeometry;
701 else
702 rc = VERR_VD_GEOMETRY_NOT_SET;
703
704 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
705 return rc;
706}
707
708/** @copydoc VDIMAGEBACKEND::pfnSetLCHSGeometry */
709static DECLCALLBACK(int) rawSetLCHSGeometry(void *pBackendData,
710 PCVDGEOMETRY pLCHSGeometry)
711{
712 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n",
713 pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
714 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
715 int rc = VINF_SUCCESS;
716
717 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
718
719 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
720 rc = VERR_VD_IMAGE_READ_ONLY;
721 else
722 pImage->LCHSGeometry = *pLCHSGeometry;
723
724 LogFlowFunc(("returns %Rrc\n", rc));
725 return rc;
726}
727
728/** @copydoc VDIMAGEBACKEND::pfnGetImageFlags */
729static DECLCALLBACK(unsigned) rawGetImageFlags(void *pBackendData)
730{
731 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
732 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
733
734 AssertPtrReturn(pImage, 0);
735
736 LogFlowFunc(("returns %#x\n", pImage->uImageFlags));
737 return pImage->uImageFlags;
738}
739
740/** @copydoc VDIMAGEBACKEND::pfnGetOpenFlags */
741static DECLCALLBACK(unsigned) rawGetOpenFlags(void *pBackendData)
742{
743 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
744 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
745
746 AssertPtrReturn(pImage, 0);
747
748 LogFlowFunc(("returns %#x\n", pImage->uOpenFlags));
749 return pImage->uOpenFlags;
750}
751
752/** @copydoc VDIMAGEBACKEND::pfnSetOpenFlags */
753static DECLCALLBACK(int) rawSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
754{
755 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
756 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
757 int rc = VINF_SUCCESS;
758
759 /* Image must be opened and the new flags must be valid. */
760 if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
761 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
762 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
763 rc = VERR_INVALID_PARAMETER;
764 else
765 {
766 /* Implement this operation via reopening the image. */
767 rc = rawFreeImage(pImage, false);
768 if (RT_SUCCESS(rc))
769 rc = rawOpenImage(pImage, uOpenFlags);
770 }
771
772 LogFlowFunc(("returns %Rrc\n", rc));
773 return rc;
774}
775
776/** @copydoc VDIMAGEBACKEND::pfnGetComment */
777static DECLCALLBACK(int) rawGetComment(void *pBackendData, char *pszComment,
778 size_t cbComment)
779{
780 RT_NOREF2(pszComment, cbComment);
781 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
782 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
783
784 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
785
786 LogFlowFunc(("returns %Rrc comment='%s'\n", VERR_NOT_SUPPORTED, pszComment));
787 return VERR_NOT_SUPPORTED;
788}
789
790/** @copydoc VDIMAGEBACKEND::pfnSetComment */
791static DECLCALLBACK(int) rawSetComment(void *pBackendData, const char *pszComment)
792{
793 RT_NOREF1(pszComment);
794 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
795 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
796
797 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
798
799 int rc;
800 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
801 rc = VERR_VD_IMAGE_READ_ONLY;
802 else
803 rc = VERR_NOT_SUPPORTED;
804
805 LogFlowFunc(("returns %Rrc\n", rc));
806 return rc;
807}
808
809/** @copydoc VDIMAGEBACKEND::pfnGetUuid */
810static DECLCALLBACK(int) rawGetUuid(void *pBackendData, PRTUUID pUuid)
811{
812 RT_NOREF1(pUuid);
813 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
814 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
815
816 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
817
818 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
819 return VERR_NOT_SUPPORTED;
820}
821
822/** @copydoc VDIMAGEBACKEND::pfnSetUuid */
823static DECLCALLBACK(int) rawSetUuid(void *pBackendData, PCRTUUID pUuid)
824{
825 RT_NOREF1(pUuid);
826 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
827 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
828
829 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
830
831 int rc;
832 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
833 rc = VERR_VD_IMAGE_READ_ONLY;
834 else
835 rc = VERR_NOT_SUPPORTED;
836
837 LogFlowFunc(("returns %Rrc\n", rc));
838 return rc;
839}
840
841/** @copydoc VDIMAGEBACKEND::pfnGetModificationUuid */
842static DECLCALLBACK(int) rawGetModificationUuid(void *pBackendData, PRTUUID pUuid)
843{
844 RT_NOREF1(pUuid);
845 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
846 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
847
848 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
849
850 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
851 return VERR_NOT_SUPPORTED;
852}
853
854/** @copydoc VDIMAGEBACKEND::pfnSetModificationUuid */
855static DECLCALLBACK(int) rawSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
856{
857 RT_NOREF1(pUuid);
858 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
859 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
860
861 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
862
863 int rc;
864 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
865 rc = VERR_VD_IMAGE_READ_ONLY;
866 else
867 rc = VERR_NOT_SUPPORTED;
868
869 LogFlowFunc(("returns %Rrc\n", rc));
870 return rc;
871}
872
873/** @copydoc VDIMAGEBACKEND::pfnGetParentUuid */
874static DECLCALLBACK(int) rawGetParentUuid(void *pBackendData, PRTUUID pUuid)
875{
876 RT_NOREF1(pUuid);
877 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
878 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
879
880 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
881
882 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid));
883 return VERR_NOT_SUPPORTED;
884}
885
886/** @copydoc VDIMAGEBACKEND::pfnSetParentUuid */
887static DECLCALLBACK(int) rawSetParentUuid(void *pBackendData, PCRTUUID pUuid)
888{
889 RT_NOREF1(pUuid);
890 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
891 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
892
893 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
894
895 int rc;
896 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
897 rc = VERR_VD_IMAGE_READ_ONLY;
898 else
899 rc = VERR_NOT_SUPPORTED;
900
901 LogFlowFunc(("returns %Rrc\n", rc));
902 return rc;
903}
904
905/** @copydoc VDIMAGEBACKEND::pfnGetParentModificationUuid */
906static DECLCALLBACK(int) rawGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
907{
908 RT_NOREF1(pUuid);
909 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
910 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
911
912 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
913
914 int rc;
915 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
916 rc = VERR_VD_IMAGE_READ_ONLY;
917 else
918 rc = VERR_NOT_SUPPORTED;
919
920 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
921 return rc;
922}
923
924/** @copydoc VDIMAGEBACKEND::pfnSetParentModificationUuid */
925static DECLCALLBACK(int) rawSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
926{
927 RT_NOREF1(pUuid);
928 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
929 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
930
931 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
932
933 int rc;
934 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
935 rc = VERR_VD_IMAGE_READ_ONLY;
936 else
937 rc = VERR_NOT_SUPPORTED;
938
939 LogFlowFunc(("returns %Rrc\n", rc));
940 return rc;
941}
942
943/** @copydoc VDIMAGEBACKEND::pfnDump */
944static DECLCALLBACK(void) rawDump(void *pBackendData)
945{
946 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
947
948 AssertPtrReturnVoid(pImage);
949 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
950 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
951 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
952 pImage->cbSize / 512);
953}
954
955
956
957const VDIMAGEBACKEND g_RawBackend =
958{
959 /* u32Version */
960 VD_IMGBACKEND_VERSION,
961 /* pszBackendName */
962 "RAW",
963 /* uBackendCaps */
964 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
965 /* paFileExtensions */
966 s_aRawFileExtensions,
967 /* paConfigInfo */
968 NULL,
969 /* pfnProbe */
970 rawProbe,
971 /* pfnOpen */
972 rawOpen,
973 /* pfnCreate */
974 rawCreate,
975 /* pfnRename */
976 rawRename,
977 /* pfnClose */
978 rawClose,
979 /* pfnRead */
980 rawRead,
981 /* pfnWrite */
982 rawWrite,
983 /* pfnFlush */
984 rawFlush,
985 /* pfnDiscard */
986 NULL,
987 /* pfnGetVersion */
988 rawGetVersion,
989 /* pfnGetSectorSize */
990 rawGetSectorSize,
991 /* pfnGetSize */
992 rawGetSize,
993 /* pfnGetFileSize */
994 rawGetFileSize,
995 /* pfnGetPCHSGeometry */
996 rawGetPCHSGeometry,
997 /* pfnSetPCHSGeometry */
998 rawSetPCHSGeometry,
999 /* pfnGetLCHSGeometry */
1000 rawGetLCHSGeometry,
1001 /* pfnSetLCHSGeometry */
1002 rawSetLCHSGeometry,
1003 /* pfnGetImageFlags */
1004 rawGetImageFlags,
1005 /* pfnGetOpenFlags */
1006 rawGetOpenFlags,
1007 /* pfnSetOpenFlags */
1008 rawSetOpenFlags,
1009 /* pfnGetComment */
1010 rawGetComment,
1011 /* pfnSetComment */
1012 rawSetComment,
1013 /* pfnGetUuid */
1014 rawGetUuid,
1015 /* pfnSetUuid */
1016 rawSetUuid,
1017 /* pfnGetModificationUuid */
1018 rawGetModificationUuid,
1019 /* pfnSetModificationUuid */
1020 rawSetModificationUuid,
1021 /* pfnGetParentUuid */
1022 rawGetParentUuid,
1023 /* pfnSetParentUuid */
1024 rawSetParentUuid,
1025 /* pfnGetParentModificationUuid */
1026 rawGetParentModificationUuid,
1027 /* pfnSetParentModificationUuid */
1028 rawSetParentModificationUuid,
1029 /* pfnDump */
1030 rawDump,
1031 /* pfnGetTimestamp */
1032 NULL,
1033 /* pfnGetParentTimestamp */
1034 NULL,
1035 /* pfnSetParentTimestamp */
1036 NULL,
1037 /* pfnGetParentFilename */
1038 NULL,
1039 /* pfnSetParentFilename */
1040 NULL,
1041 /* pfnComposeLocation */
1042 genericFileComposeLocation,
1043 /* pfnComposeName */
1044 genericFileComposeName,
1045 /* pfnCompact */
1046 NULL,
1047 /* pfnResize */
1048 NULL,
1049 /* pfnRepair */
1050 NULL,
1051 /* pfnTraverseMetadata */
1052 NULL,
1053 /* u32VersionEnd */
1054 VD_IMGBACKEND_VERSION
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