VirtualBox

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

Last change on this file since 65123 was 64272, checked in by vboxsync, 8 years ago

Storage: Doxygen fixes

  • 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 64272 2016-10-14 08:25: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 cbToRead,
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, cbToRead);
533 if (RT_SUCCESS(rc))
534 {
535 *pcbActuallyRead = cbToRead;
536 pImage->offAccess = uOffset + cbToRead;
537 }
538
539 return rc;
540}
541
542/** @copydoc VDIMAGEBACKEND::pfnWrite */
543static DECLCALLBACK(int) rawWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
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, cbToWrite, NULL, NULL);
563 if (RT_SUCCESS(rc))
564 {
565 *pcbWriteProcess = cbToWrite;
566 *pcbPostRead = 0;
567 *pcbPreRead = 0;
568 pImage->offAccess = uOffset + cbToWrite;
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