VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/RawHDDCore.cpp@ 11347

Last change on this file since 11347 was 11287, checked in by vboxsync, 16 years ago

Devices: %Vuuid -> %RTuuid (just preferred, not mandatory (yet))

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.9 KB
Line 
1/** $Id: RawHDDCore.cpp 11287 2008-08-08 22:35:40Z vboxsync $ */
2/** @file
3 * Raw Disk image, Core Code.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_VD_RAW
26#include "VBoxHDD-newInternal.h"
27#include <VBox/err.h>
28
29#include <VBox/log.h>
30#include <iprt/assert.h>
31#include <iprt/alloc.h>
32#include <iprt/file.h>
33
34
35/*******************************************************************************
36* Constants And Macros, Structures and Typedefs *
37*******************************************************************************/
38
39/**
40 * Raw image data structure.
41 */
42typedef struct RAWIMAGE
43{
44 /** Base image name. */
45 const char *pszFilename;
46 /** File descriptor. */
47 RTFILE File;
48
49 /** Error callback. */
50 PVDINTERFACE pInterfaceError;
51 /** Opaque data for error callback. */
52 PVDINTERFACEERROR pInterfaceErrorCallbacks;
53
54 /** Open flags passed by VBoxHD layer. */
55 unsigned uOpenFlags;
56 /** Image type. */
57 VDIMAGETYPE enmImageType;
58 /** Image flags defined during creation or determined during open. */
59 unsigned uImageFlags;
60 /** Total size of the image. */
61 uint64_t cbSize;
62 /** Physical geometry of this image. */
63 PDMMEDIAGEOMETRY PCHSGeometry;
64 /** Logical geometry of this image. */
65 PDMMEDIAGEOMETRY LCHSGeometry;
66
67} RAWIMAGE, *PRAWIMAGE;
68
69
70/*******************************************************************************
71* Internal Functions *
72*******************************************************************************/
73
74static int rawFlushImage(PRAWIMAGE pImage);
75static void rawFreeImage(PRAWIMAGE pImage, bool fDelete);
76
77
78/**
79 * Internal: signal an error to the frontend.
80 */
81DECLINLINE(int) rawError(PRAWIMAGE pImage, int rc, RT_SRC_POS_DECL,
82 const char *pszFormat, ...)
83{
84 va_list va;
85 va_start(va, pszFormat);
86 if (pImage->pInterfaceError)
87 pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,
88 pszFormat, va);
89 va_end(va);
90 return rc;
91}
92
93/**
94 * Internal: Open an image, constructing all necessary data structures.
95 */
96static int rawOpenImage(PRAWIMAGE pImage, unsigned uOpenFlags)
97{
98 int rc;
99 RTFILE File;
100
101 if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
102 return VERR_NOT_SUPPORTED;
103
104 pImage->uOpenFlags = uOpenFlags;
105
106 /*
107 * Open the image.
108 */
109 rc = RTFileOpen(&File, pImage->pszFilename,
110 uOpenFlags & VD_OPEN_FLAGS_READONLY
111 ? RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
112 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
113 if (RT_FAILURE(rc))
114 {
115 /* Do NOT signal an appropriate error here, as the VD layer has the
116 * choice of retrying the open if it failed. */
117 goto out;
118 }
119 pImage->File = File;
120
121 rc = RTFileGetSize(pImage->File, &pImage->cbSize);
122 if (RT_FAILURE(rc))
123 goto out;
124 if (pImage->cbSize % 512)
125 {
126 rc = VERR_VDI_INVALID_HEADER;
127 goto out;
128 }
129 pImage->enmImageType = VD_IMAGE_TYPE_FIXED;
130
131out:
132 if (RT_FAILURE(rc))
133 rawFreeImage(pImage, false);
134 return rc;
135}
136
137/**
138 * Internal: Create a raw image.
139 */
140static int rawCreateImage(PRAWIMAGE pImage, VDIMAGETYPE enmType,
141 uint64_t cbSize, unsigned uImageFlags,
142 const char *pszComment,
143 PCPDMMEDIAGEOMETRY pPCHSGeometry,
144 PCPDMMEDIAGEOMETRY pLCHSGeometry,
145 PFNVMPROGRESS pfnProgress, void *pvUser,
146 unsigned uPercentStart, unsigned uPercentSpan)
147{
148 int rc;
149 RTFILE File;
150 RTFOFF cbFree = 0;
151 uint64_t uOff;
152 size_t cbBuf = 128 * _1K;
153 void *pvBuf = NULL;
154
155 if (enmType != VD_IMAGE_TYPE_FIXED)
156 {
157 rc = rawError(pImage, VERR_VDI_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename);
158 goto out;
159 }
160
161 pImage->enmImageType = enmType;
162 pImage->uImageFlags = uImageFlags;
163 pImage->PCHSGeometry = *pPCHSGeometry;
164 pImage->LCHSGeometry = *pLCHSGeometry;
165
166 /* Create image file. */
167 rc = RTFileOpen(&File, pImage->pszFilename,
168 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_ALL);
169 if (RT_FAILURE(rc))
170 {
171 rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename);
172 goto out;
173 }
174 pImage->File = File;
175
176 /* Check the free space on the disk and leave early if there is not
177 * sufficient space available. */
178 rc = RTFsQuerySizes(pImage->pszFilename, NULL, &cbFree, NULL, NULL);
179 if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize))
180 {
181 rc = rawError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
182 goto out;
183 }
184
185 /* Allocate & commit whole file if fixed image, it must be more
186 * effective than expanding file by write operations. */
187 rc = RTFileSetSize(File, cbSize);
188 if (RT_FAILURE(rc))
189 {
190 rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: setting image size failed for '%s'"), pImage->pszFilename);
191 goto out;
192 }
193
194 /* Fill image with zeroes. We do this for every fixed-size image since on
195 * some systems (for example Windows Vista), it takes ages to write a block
196 * near the end of a sparse file and the guest could complain about an ATA
197 * timeout. */
198 pvBuf = RTMemTmpAllocZ(cbBuf);
199 if (!pvBuf)
200 {
201 rc = VERR_NO_MEMORY;
202 goto out;
203 }
204
205 uOff = 0;
206 /* Write data to all image blocks. */
207 while (uOff < cbSize)
208 {
209 unsigned cbChunk = (unsigned)RT_MIN(cbSize, cbBuf);
210
211 rc = RTFileWriteAt(File, uOff, pvBuf, cbChunk, NULL);
212 if (RT_FAILURE(rc))
213 {
214 rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: writing block failed for '%s'"), pImage->pszFilename);
215 goto out;
216 }
217
218 uOff += cbChunk;
219
220 if (pfnProgress)
221 {
222 rc = pfnProgress(NULL /* WARNING! pVM=NULL */,
223 uPercentStart + uOff * uPercentSpan * 98 / (cbSize * 100),
224 pvUser);
225 if (RT_FAILURE(rc))
226 goto out;
227 }
228 }
229 RTMemTmpFree(pvBuf);
230
231 if (RT_SUCCESS(rc) && pfnProgress)
232 pfnProgress(NULL /* WARNING! pVM=NULL */,
233 uPercentStart + uPercentSpan * 98 / 100, pvUser);
234
235 pImage->enmImageType = enmType;
236 pImage->cbSize = cbSize;
237
238 rc = rawFlushImage(pImage);
239
240out:
241 if (RT_SUCCESS(rc) && pfnProgress)
242 pfnProgress(NULL /* WARNING! pVM=NULL */,
243 uPercentStart + uPercentSpan, pvUser);
244
245 if (RT_FAILURE(rc))
246 rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
247 return rc;
248}
249
250/**
251 * Internal. Free all allocated space for representing an image, and optionally
252 * delete the image from disk.
253 */
254static void rawFreeImage(PRAWIMAGE pImage, bool fDelete)
255{
256 Assert(pImage);
257
258 if (pImage->enmImageType)
259 {
260 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
261 rawFlushImage(pImage);
262 }
263 if (pImage->File != NIL_RTFILE)
264 {
265 RTFileClose(pImage->File);
266 pImage->File = NIL_RTFILE;
267 }
268 if (fDelete && pImage->pszFilename)
269 RTFileDelete(pImage->pszFilename);
270}
271
272/**
273 * Internal. Flush image data to disk.
274 */
275static int rawFlushImage(PRAWIMAGE pImage)
276{
277 int rc = VINF_SUCCESS;
278
279 if ( pImage->File != NIL_RTFILE
280 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
281 rc = RTFileFlush(pImage->File);
282
283 return rc;
284}
285
286
287/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
288static int rawCheckIfValid(const char *pszFilename)
289{
290 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
291 int rc = VINF_SUCCESS;
292
293 if ( !VALID_PTR(pszFilename)
294 || !*pszFilename)
295 {
296 rc = VERR_INVALID_PARAMETER;
297 goto out;
298 }
299
300 /* Always return failure, to avoid opening everything as a raw image. */
301 rc = VERR_VDI_INVALID_HEADER;
302
303out:
304 LogFlowFunc(("returns %Rrc\n", rc));
305 return rc;
306}
307
308/** @copydoc VBOXHDDBACKEND::pfnOpen */
309static int rawOpen(const char *pszFilename, unsigned uOpenFlags,
310 PVDINTERFACE pInterfaces, void **ppBackendData)
311{
312 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x ppBackendData=%#p\n", pszFilename, uOpenFlags, ppBackendData));
313 int rc;
314 PRAWIMAGE pImage;
315
316 /* Check open flags. All valid flags are supported. */
317 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
318 {
319 rc = VERR_INVALID_PARAMETER;
320 goto out;
321 }
322
323 /* Check remaining arguments. */
324 if ( !VALID_PTR(pszFilename)
325 || !*pszFilename)
326 {
327 rc = VERR_INVALID_PARAMETER;
328 goto out;
329 }
330
331
332 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
333 if (!pImage)
334 {
335 rc = VERR_NO_MEMORY;
336 goto out;
337 }
338 pImage->pszFilename = pszFilename;
339 pImage->File = NIL_RTFILE;
340 pImage->pInterfaceError = NULL;
341 pImage->pInterfaceErrorCallbacks = NULL;
342
343 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR);
344 if (pImage->pInterfaceError)
345 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
346
347 rc = rawOpenImage(pImage, uOpenFlags);
348 if (RT_SUCCESS(rc))
349 *ppBackendData = pImage;
350
351out:
352 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
353 return rc;
354}
355
356/** @copydoc VBOXHDDBACKEND::pfnCreate */
357static int rawCreate(const char *pszFilename, VDIMAGETYPE enmType,
358 uint64_t cbSize, unsigned uImageFlags,
359 const char *pszComment,
360 PCPDMMEDIAGEOMETRY pPCHSGeometry,
361 PCPDMMEDIAGEOMETRY pLCHSGeometry,
362 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress,
363 void *pvUser, unsigned uPercentStart,
364 unsigned uPercentSpan, PVDINTERFACE pInterfaces,
365 void **ppBackendData)
366{
367 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u pInterfaces=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pInterfaces, ppBackendData));
368 int rc;
369 PRAWIMAGE pImage;
370
371 /* Check open flags. All valid flags are supported. */
372 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
373 {
374 rc = VERR_INVALID_PARAMETER;
375 goto out;
376 }
377
378 /* Check remaining arguments. */
379 if ( !VALID_PTR(pszFilename)
380 || !*pszFilename
381 || (enmType != VD_IMAGE_TYPE_FIXED)
382 || !VALID_PTR(pPCHSGeometry)
383 || !VALID_PTR(pLCHSGeometry))
384 {
385 rc = VERR_INVALID_PARAMETER;
386 goto out;
387 }
388
389 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
390 if (!pImage)
391 {
392 rc = VERR_NO_MEMORY;
393 goto out;
394 }
395 pImage->pszFilename = pszFilename;
396 pImage->File = NIL_RTFILE;
397
398 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR);
399 if (pImage->pInterfaceError)
400 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
401
402
403 rc = rawCreateImage(pImage, enmType, cbSize, uImageFlags, pszComment,
404 pPCHSGeometry, pLCHSGeometry,
405 pfnProgress, pvUser, uPercentStart, uPercentSpan);
406 if (RT_SUCCESS(rc))
407 {
408 /* So far the image is opened in read/write mode. Make sure the
409 * image is opened in read-only mode if the caller requested that. */
410 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
411 {
412 rawFreeImage(pImage, false);
413 rc = rawOpenImage(pImage, uOpenFlags);
414 if (RT_FAILURE(rc))
415 goto out;
416 }
417 *ppBackendData = pImage;
418 }
419
420out:
421 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
422 return rc;
423}
424
425/** @copydoc VBOXHDDBACKEND::pfnRename */
426static int rawRename(void *pBackendData, const char *pszFilename)
427{
428 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
429 int rc = VERR_NOT_IMPLEMENTED;
430
431 LogFlowFunc(("returns %Rrc\n", rc));
432 return rc;
433}
434
435/** @copydoc VBOXHDDBACKEND::pfnClose */
436static int rawClose(void *pBackendData, bool fDelete)
437{
438 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
439 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
440 int rc = VINF_SUCCESS;
441
442 /* Freeing a never allocated image (e.g. because the open failed) is
443 * not signalled as an error. After all nothing bad happens. */
444 if (pImage)
445 rawFreeImage(pImage, fDelete);
446
447 LogFlowFunc(("returns %Rrc\n", rc));
448 return rc;
449}
450
451/** @copydoc VBOXHDDBACKEND::pfnRead */
452static int rawRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
453 size_t cbToRead, size_t *pcbActuallyRead)
454{
455 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
456 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
457 int rc;
458
459 Assert(pImage);
460 Assert(uOffset % 512 == 0);
461 Assert(cbToRead % 512 == 0);
462
463 if ( uOffset + cbToRead > pImage->cbSize
464 || cbToRead == 0)
465 {
466 rc = VERR_INVALID_PARAMETER;
467 goto out;
468 }
469
470 rc = RTFileReadAt(pImage->File, uOffset, pvBuf, cbToRead, NULL);
471 *pcbActuallyRead = cbToRead;
472
473out:
474 LogFlowFunc(("returns %Rrc\n", rc));
475 return rc;
476}
477
478/** @copydoc VBOXHDDBACKEND::pfnWrite */
479static int rawWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
480 size_t cbToWrite, size_t *pcbWriteProcess,
481 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
482{
483 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
484 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
485 int rc;
486
487 Assert(pImage);
488 Assert(uOffset % 512 == 0);
489 Assert(cbToWrite % 512 == 0);
490
491 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
492 {
493 rc = VERR_VDI_IMAGE_READ_ONLY;
494 goto out;
495 }
496
497 if ( uOffset + cbToWrite > pImage->cbSize
498 || cbToWrite == 0)
499 {
500 rc = VERR_INVALID_PARAMETER;
501 goto out;
502 }
503
504 rc = RTFileWriteAt(pImage->File, uOffset, pvBuf, cbToWrite, NULL);
505 if (pcbWriteProcess)
506 *pcbWriteProcess = cbToWrite;
507
508out:
509 LogFlowFunc(("returns %Rrc\n", rc));
510 return rc;
511}
512
513/** @copydoc VBOXHDDBACKEND::pfnFlush */
514static int rawFlush(void *pBackendData)
515{
516 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
517 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
518 int rc;
519
520 rc = rawFlushImage(pImage);
521 LogFlowFunc(("returns %Rrc\n", rc));
522 return rc;
523}
524
525/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
526static unsigned rawGetVersion(void *pBackendData)
527{
528 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
529 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
530
531 Assert(pImage);
532
533 if (pImage)
534 return 1;
535 else
536 return 0;
537}
538
539/** @copydoc VBOXHDDBACKEND::pfnGetImageType */
540static int rawGetImageType(void *pBackendData, PVDIMAGETYPE penmImageType)
541{
542 LogFlowFunc(("pBackendData=%#p penmImageType=%#p\n", pBackendData, penmImageType));
543 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
544 int rc = VINF_SUCCESS;
545
546 Assert(pImage);
547 Assert(penmImageType);
548
549 if (pImage)
550 *penmImageType = pImage->enmImageType;
551 else
552 rc = VERR_VDI_NOT_OPENED;
553
554 LogFlowFunc(("returns %Rrc enmImageType=%u\n", rc, *penmImageType));
555 return rc;
556}
557
558/** @copydoc VBOXHDDBACKEND::pfnGetSize */
559static uint64_t rawGetSize(void *pBackendData)
560{
561 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
562 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
563
564 Assert(pImage);
565
566 if (pImage)
567 return pImage->cbSize;
568 else
569 return 0;
570}
571
572/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
573static uint64_t rawGetFileSize(void *pBackendData)
574{
575 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
576 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
577 uint64_t cb = 0;
578
579 Assert(pImage);
580
581 if (pImage)
582 {
583 uint64_t cbFile;
584 if (pImage->File != NIL_RTFILE)
585 {
586 int rc = RTFileGetSize(pImage->File, &cbFile);
587 if (RT_SUCCESS(rc))
588 cb += cbFile;
589 }
590 }
591
592 LogFlowFunc(("returns %lld\n", cb));
593 return cb;
594}
595
596/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
597static int rawGetPCHSGeometry(void *pBackendData,
598 PPDMMEDIAGEOMETRY pPCHSGeometry)
599{
600 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
601 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
602 int rc;
603
604 Assert(pImage);
605
606 if (pImage)
607 {
608 if (pImage->PCHSGeometry.cCylinders)
609 {
610 *pPCHSGeometry = pImage->PCHSGeometry;
611 rc = VINF_SUCCESS;
612 }
613 else
614 rc = VERR_VDI_GEOMETRY_NOT_SET;
615 }
616 else
617 rc = VERR_VDI_NOT_OPENED;
618
619 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
620 return rc;
621}
622
623/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
624static int rawSetPCHSGeometry(void *pBackendData,
625 PCPDMMEDIAGEOMETRY pPCHSGeometry)
626{
627 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
628 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
629 int rc;
630
631 Assert(pImage);
632
633 if (pImage)
634 {
635 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
636 {
637 rc = VERR_VDI_IMAGE_READ_ONLY;
638 goto out;
639 }
640
641 pImage->PCHSGeometry = *pPCHSGeometry;
642 rc = VINF_SUCCESS;
643 }
644 else
645 rc = VERR_VDI_NOT_OPENED;
646
647out:
648 LogFlowFunc(("returns %Rrc\n", rc));
649 return rc;
650}
651
652/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
653static int rawGetLCHSGeometry(void *pBackendData,
654 PPDMMEDIAGEOMETRY pLCHSGeometry)
655{
656 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
657 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
658 int rc;
659
660 Assert(pImage);
661
662 if (pImage)
663 {
664 if (pImage->LCHSGeometry.cCylinders)
665 {
666 *pLCHSGeometry = pImage->LCHSGeometry;
667 rc = VINF_SUCCESS;
668 }
669 else
670 rc = VERR_VDI_GEOMETRY_NOT_SET;
671 }
672 else
673 rc = VERR_VDI_NOT_OPENED;
674
675 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
676 return rc;
677}
678
679/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
680static int rawSetLCHSGeometry(void *pBackendData,
681 PCPDMMEDIAGEOMETRY pLCHSGeometry)
682{
683 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
684 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
685 int rc;
686
687 Assert(pImage);
688
689 if (pImage)
690 {
691 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
692 {
693 rc = VERR_VDI_IMAGE_READ_ONLY;
694 goto out;
695 }
696
697 pImage->LCHSGeometry = *pLCHSGeometry;
698 rc = VINF_SUCCESS;
699 }
700 else
701 rc = VERR_VDI_NOT_OPENED;
702
703out:
704 LogFlowFunc(("returns %Rrc\n", rc));
705 return rc;
706}
707
708/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
709static unsigned rawGetImageFlags(void *pBackendData)
710{
711 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
712 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
713 unsigned uImageFlags;
714
715 Assert(pImage);
716
717 if (pImage)
718 uImageFlags = pImage->uImageFlags;
719 else
720 uImageFlags = 0;
721
722 LogFlowFunc(("returns %#x\n", uImageFlags));
723 return uImageFlags;
724}
725
726/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
727static unsigned rawGetOpenFlags(void *pBackendData)
728{
729 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
730 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
731 unsigned uOpenFlags;
732
733 Assert(pImage);
734
735 if (pImage)
736 uOpenFlags = pImage->uOpenFlags;
737 else
738 uOpenFlags = 0;
739
740 LogFlowFunc(("returns %#x\n", uOpenFlags));
741 return uOpenFlags;
742}
743
744/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
745static int rawSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
746{
747 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
748 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
749 int rc;
750
751 /* Image must be opened and the new flags must be valid. Just readonly flag
752 * is supported. */
753 if (!pImage || uOpenFlags & ~VD_OPEN_FLAGS_READONLY)
754 {
755 rc = VERR_INVALID_PARAMETER;
756 goto out;
757 }
758
759 /* Implement this operation via reopening the image. */
760 rawFreeImage(pImage, false);
761 rc = rawOpenImage(pImage, uOpenFlags);
762
763out:
764 LogFlowFunc(("returns %Rrc\n", rc));
765 return rc;
766}
767
768/** @copydoc VBOXHDDBACKEND::pfnGetComment */
769static int rawGetComment(void *pBackendData, char *pszComment,
770 size_t cbComment)
771{
772 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
773 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
774 int rc;
775
776 Assert(pImage);
777
778 if (pImage)
779 {
780 if (pszComment)
781 *pszComment = '\0';
782 rc = VINF_SUCCESS;
783 }
784 else
785 rc = VERR_VDI_NOT_OPENED;
786
787 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
788 return rc;
789}
790
791/** @copydoc VBOXHDDBACKEND::pfnSetComment */
792static int rawSetComment(void *pBackendData, const char *pszComment)
793{
794 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
795 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
796 int rc;
797
798 Assert(pImage);
799
800 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
801 {
802 rc = VERR_VDI_IMAGE_READ_ONLY;
803 goto out;
804 }
805
806 if (pImage)
807 rc = VERR_NOT_SUPPORTED;
808 else
809 rc = VERR_VDI_NOT_OPENED;
810
811out:
812 LogFlowFunc(("returns %Rrc\n", rc));
813 return rc;
814}
815
816/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
817static int rawGetUuid(void *pBackendData, PRTUUID pUuid)
818{
819 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
820 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
821 int rc;
822
823 Assert(pImage);
824
825 if (pImage)
826 rc = VERR_NOT_SUPPORTED;
827 else
828 rc = VERR_VDI_NOT_OPENED;
829
830 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
831 return rc;
832}
833
834/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
835static int rawSetUuid(void *pBackendData, PCRTUUID pUuid)
836{
837 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
838 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
839 int rc;
840
841 LogFlowFunc(("%RTuuid\n", pUuid));
842 Assert(pImage);
843
844 if (pImage)
845 {
846 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
847 rc = VERR_NOT_SUPPORTED;
848 else
849 rc = VERR_VDI_IMAGE_READ_ONLY;
850 }
851 else
852 rc = VERR_VDI_NOT_OPENED;
853
854 LogFlowFunc(("returns %Rrc\n", rc));
855 return rc;
856}
857
858/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
859static int rawGetModificationUuid(void *pBackendData, PRTUUID pUuid)
860{
861 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
862 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
863 int rc;
864
865 Assert(pImage);
866
867 if (pImage)
868 rc = VERR_NOT_SUPPORTED;
869 else
870 rc = VERR_VDI_NOT_OPENED;
871
872 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
873 return rc;
874}
875
876/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
877static int rawSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
878{
879 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
880 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
881 int rc;
882
883 Assert(pImage);
884
885 if (pImage)
886 {
887 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
888 rc = VERR_NOT_SUPPORTED;
889 else
890 rc = VERR_VDI_IMAGE_READ_ONLY;
891 }
892 else
893 rc = VERR_VDI_NOT_OPENED;
894
895 LogFlowFunc(("returns %Rrc\n", rc));
896 return rc;
897}
898
899/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
900static int rawGetParentUuid(void *pBackendData, PRTUUID pUuid)
901{
902 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
903 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
904 int rc;
905
906 Assert(pImage);
907
908 if (pImage)
909 rc = VERR_NOT_SUPPORTED;
910 else
911 rc = VERR_VDI_NOT_OPENED;
912
913 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
914 return rc;
915}
916
917/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
918static int rawSetParentUuid(void *pBackendData, PCRTUUID pUuid)
919{
920 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
921 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
922 int rc;
923
924 Assert(pImage);
925
926 if (pImage)
927 {
928 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
929 rc = VERR_NOT_SUPPORTED;
930 else
931 rc = VERR_VDI_IMAGE_READ_ONLY;
932 }
933 else
934 rc = VERR_VDI_NOT_OPENED;
935
936 LogFlowFunc(("returns %Rrc\n", rc));
937 return rc;
938}
939
940/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
941static int rawGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
942{
943 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
944 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
945 int rc;
946
947 Assert(pImage);
948
949 if (pImage)
950 rc = VERR_NOT_SUPPORTED;
951 else
952 rc = VERR_VDI_NOT_OPENED;
953
954 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
955 return rc;
956}
957
958/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
959static int rawSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
960{
961 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
962 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
963 int rc;
964
965 Assert(pImage);
966
967 if (pImage)
968 {
969 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
970 rc = VERR_NOT_SUPPORTED;
971 else
972 rc = VERR_VDI_IMAGE_READ_ONLY;
973 }
974 else
975 rc = VERR_VDI_NOT_OPENED;
976
977 LogFlowFunc(("returns %Rrc\n", rc));
978 return rc;
979}
980
981/** @copydoc VBOXHDDBACKEND::pfnDump */
982static void rawDump(void *pBackendData)
983{
984 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
985
986 Assert(pImage);
987 if (pImage)
988 {
989 RTLogPrintf("Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
990 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
991 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
992 pImage->cbSize / 512);
993 }
994}
995
996static int rawGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
997{
998 int rc = VERR_NOT_IMPLEMENTED;
999 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1000 return rc;
1001}
1002
1003static int rawGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
1004{
1005 int rc = VERR_NOT_IMPLEMENTED;
1006 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1007 return rc;
1008}
1009
1010static int rawSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
1011{
1012 int rc = VERR_NOT_IMPLEMENTED;
1013 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1014 return rc;
1015}
1016
1017static int rawGetParentFilename(void *pvBackendData, char **ppszParentFilename)
1018{
1019 int rc = VERR_NOT_IMPLEMENTED;
1020 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1021 return rc;
1022}
1023
1024static int rawSetParentFilename(void *pvBackendData, const char *pszParentFilename)
1025{
1026 int rc = VERR_NOT_IMPLEMENTED;
1027 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1028 return rc;
1029}
1030
1031static bool rawIsAsyncIOSupported(void *pvBackendData)
1032{
1033 return false;
1034}
1035
1036static int rawAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
1037 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
1038{
1039 int rc = VERR_NOT_IMPLEMENTED;
1040 LogFlowFunc(("returns %Rrc\n", rc));
1041 return rc;
1042}
1043
1044static int rawAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
1045 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
1046{
1047 int rc = VERR_NOT_IMPLEMENTED;
1048 LogFlowFunc(("returns %Rrc\n", rc));
1049 return rc;
1050}
1051
1052VBOXHDDBACKEND g_RawBackend =
1053{
1054 /* pszBackendName */
1055 "raw",
1056 /* cbSize */
1057 sizeof(VBOXHDDBACKEND),
1058 /* uBackendCaps */
1059 VD_CAP_CREATE_FIXED | VD_CAP_FILE,
1060 /* pfnCheckIfValid */
1061 rawCheckIfValid,
1062 /* pfnOpen */
1063 rawOpen,
1064 /* pfnCreate */
1065 rawCreate,
1066 /* pfnRename */
1067 rawRename,
1068 /* pfnClose */
1069 rawClose,
1070 /* pfnRead */
1071 rawRead,
1072 /* pfnWrite */
1073 rawWrite,
1074 /* pfnFlush */
1075 rawFlush,
1076 /* pfnGetVersion */
1077 rawGetVersion,
1078 /* pfnGetImageType */
1079 rawGetImageType,
1080 /* pfnGetSize */
1081 rawGetSize,
1082 /* pfnGetFileSize */
1083 rawGetFileSize,
1084 /* pfnGetPCHSGeometry */
1085 rawGetPCHSGeometry,
1086 /* pfnSetPCHSGeometry */
1087 rawSetPCHSGeometry,
1088 /* pfnGetLCHSGeometry */
1089 rawGetLCHSGeometry,
1090 /* pfnSetLCHSGeometry */
1091 rawSetLCHSGeometry,
1092 /* pfnGetImageFlags */
1093 rawGetImageFlags,
1094 /* pfnGetOpenFlags */
1095 rawGetOpenFlags,
1096 /* pfnSetOpenFlags */
1097 rawSetOpenFlags,
1098 /* pfnGetComment */
1099 rawGetComment,
1100 /* pfnSetComment */
1101 rawSetComment,
1102 /* pfnGetUuid */
1103 rawGetUuid,
1104 /* pfnSetUuid */
1105 rawSetUuid,
1106 /* pfnGetModificationUuid */
1107 rawGetModificationUuid,
1108 /* pfnSetModificationUuid */
1109 rawSetModificationUuid,
1110 /* pfnGetParentUuid */
1111 rawGetParentUuid,
1112 /* pfnSetParentUuid */
1113 rawSetParentUuid,
1114 /* pfnGetParentModificationUuid */
1115 rawGetParentModificationUuid,
1116 /* pfnSetParentModificationUuid */
1117 rawSetParentModificationUuid,
1118 /* pfnDump */
1119 rawDump,
1120 /* pfnGetTimeStamp */
1121 rawGetTimeStamp,
1122 /* pfnGetParentTimeStamp */
1123 rawGetParentTimeStamp,
1124 /* pfnSetParentTimeStamp */
1125 rawSetParentTimeStamp,
1126 /* pfnGetParentFilename */
1127 rawGetParentFilename,
1128 /* pfnSetParentFilename */
1129 rawSetParentFilename,
1130 /* pfnIsAsyncIOSupported */
1131 rawIsAsyncIOSupported,
1132 /* pfnAsyncRead */
1133 rawAsyncRead,
1134 /* pfnAsyncWrite */
1135 rawAsyncWrite
1136};
1137
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