VirtualBox

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

最後變更 在這個檔案從10764是 10715,由 vboxsync 提交於 17 年 前

Merge async I/O for VMDK backend from private branch

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 31.0 KB
 
1/** $Id: RawHDDCore.cpp 10715 2008-07-16 22:38:23Z 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.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * 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 (VBOX_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 (VBOX_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 (VBOX_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 (VBOX_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 (VBOX_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 (VBOX_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 (VBOX_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 (VBOX_FAILURE(rc))
226 goto out;
227 }
228 }
229 RTMemTmpFree(pvBuf);
230
231 if (VBOX_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 (VBOX_SUCCESS(rc) && pfnProgress)
242 pfnProgress(NULL /* WARNING! pVM=NULL */,
243 uPercentStart + uPercentSpan, pvUser);
244
245 if (VBOX_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 %Vrc\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->pCallbacks);
346
347 rc = rawOpenImage(pImage, uOpenFlags);
348 if (VBOX_SUCCESS(rc))
349 *ppBackendData = pImage;
350
351out:
352 LogFlowFunc(("returns %Vrc (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 (VBOX_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 (VBOX_FAILURE(rc))
415 goto out;
416 }
417 *ppBackendData = pImage;
418 }
419
420out:
421 LogFlowFunc(("returns %Vrc (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 %Vrc\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 %Vrc\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 %Vrc\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 %Vrc\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 %Vrc\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 %Vrc 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 (VBOX_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 %Vrc (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 %Vrc\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 %Vrc (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 %Vrc\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 const char *pszFilename;
751
752 /* Image must be opened and the new flags must be valid. Just readonly flag
753 * is supported. */
754 if (!pImage || uOpenFlags & ~VD_OPEN_FLAGS_READONLY)
755 {
756 rc = VERR_INVALID_PARAMETER;
757 goto out;
758 }
759
760 /* Implement this operation via reopening the image. */
761 pszFilename = pImage->pszFilename;
762 rawFreeImage(pImage, false);
763 rc = rawOpenImage(pImage, uOpenFlags);
764
765out:
766 LogFlowFunc(("returns %Vrc\n", rc));
767 return rc;
768}
769
770/** @copydoc VBOXHDDBACKEND::pfnGetComment */
771static int rawGetComment(void *pBackendData, char *pszComment,
772 size_t cbComment)
773{
774 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
775 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
776 int rc;
777
778 Assert(pImage);
779
780 if (pImage)
781 {
782 if (pszComment)
783 *pszComment = '\0';
784 rc = VINF_SUCCESS;
785 }
786 else
787 rc = VERR_VDI_NOT_OPENED;
788
789 LogFlowFunc(("returns %Vrc comment='%s'\n", rc, pszComment));
790 return rc;
791}
792
793/** @copydoc VBOXHDDBACKEND::pfnSetComment */
794static int rawSetComment(void *pBackendData, const char *pszComment)
795{
796 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
797 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
798 int rc;
799
800 Assert(pImage);
801
802 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
803 {
804 rc = VERR_VDI_IMAGE_READ_ONLY;
805 goto out;
806 }
807
808 if (pImage)
809 rc = VERR_NOT_SUPPORTED;
810 else
811 rc = VERR_VDI_NOT_OPENED;
812
813out:
814 LogFlowFunc(("returns %Vrc\n", rc));
815 return rc;
816}
817
818/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
819static int rawGetUuid(void *pBackendData, PRTUUID pUuid)
820{
821 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
822 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
823 int rc;
824
825 Assert(pImage);
826
827 if (pImage)
828 rc = VERR_NOT_SUPPORTED;
829 else
830 rc = VERR_VDI_NOT_OPENED;
831
832 LogFlowFunc(("returns %Vrc (%Vuuid)\n", rc, pUuid));
833 return rc;
834}
835
836/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
837static int rawSetUuid(void *pBackendData, PCRTUUID pUuid)
838{
839 LogFlowFunc(("pBackendData=%#p Uuid=%Vuuid\n", pBackendData, pUuid));
840 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
841 int rc;
842
843 LogFlowFunc(("%Vuuid\n", pUuid));
844 Assert(pImage);
845
846 if (pImage)
847 {
848 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
849 rc = VERR_NOT_SUPPORTED;
850 else
851 rc = VERR_VDI_IMAGE_READ_ONLY;
852 }
853 else
854 rc = VERR_VDI_NOT_OPENED;
855
856 LogFlowFunc(("returns %Vrc\n", rc));
857 return rc;
858}
859
860/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
861static int rawGetModificationUuid(void *pBackendData, PRTUUID pUuid)
862{
863 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
864 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
865 int rc;
866
867 Assert(pImage);
868
869 if (pImage)
870 rc = VERR_NOT_SUPPORTED;
871 else
872 rc = VERR_VDI_NOT_OPENED;
873
874 LogFlowFunc(("returns %Vrc (%Vuuid)\n", rc, pUuid));
875 return rc;
876}
877
878/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
879static int rawSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
880{
881 LogFlowFunc(("pBackendData=%#p Uuid=%Vuuid\n", pBackendData, pUuid));
882 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
883 int rc;
884
885 Assert(pImage);
886
887 if (pImage)
888 {
889 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
890 rc = VERR_NOT_SUPPORTED;
891 else
892 rc = VERR_VDI_IMAGE_READ_ONLY;
893 }
894 else
895 rc = VERR_VDI_NOT_OPENED;
896
897 LogFlowFunc(("returns %Vrc\n", rc));
898 return rc;
899}
900
901/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
902static int rawGetParentUuid(void *pBackendData, PRTUUID pUuid)
903{
904 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
905 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
906 int rc;
907
908 Assert(pImage);
909
910 if (pImage)
911 rc = VERR_NOT_SUPPORTED;
912 else
913 rc = VERR_VDI_NOT_OPENED;
914
915 LogFlowFunc(("returns %Vrc (%Vuuid)\n", rc, pUuid));
916 return rc;
917}
918
919/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
920static int rawSetParentUuid(void *pBackendData, PCRTUUID pUuid)
921{
922 LogFlowFunc(("pBackendData=%#p Uuid=%Vuuid\n", pBackendData, pUuid));
923 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
924 int rc;
925
926 Assert(pImage);
927
928 if (pImage)
929 {
930 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
931 rc = VERR_NOT_SUPPORTED;
932 else
933 rc = VERR_VDI_IMAGE_READ_ONLY;
934 }
935 else
936 rc = VERR_VDI_NOT_OPENED;
937
938 LogFlowFunc(("returns %Vrc\n", rc));
939 return rc;
940}
941
942/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
943static int rawGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
944{
945 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
946 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
947 int rc;
948
949 Assert(pImage);
950
951 if (pImage)
952 rc = VERR_NOT_SUPPORTED;
953 else
954 rc = VERR_VDI_NOT_OPENED;
955
956 LogFlowFunc(("returns %Vrc (%Vuuid)\n", rc, pUuid));
957 return rc;
958}
959
960/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
961static int rawSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
962{
963 LogFlowFunc(("pBackendData=%#p Uuid=%Vuuid\n", pBackendData, pUuid));
964 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
965 int rc;
966
967 Assert(pImage);
968
969 if (pImage)
970 {
971 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
972 rc = VERR_NOT_SUPPORTED;
973 else
974 rc = VERR_VDI_IMAGE_READ_ONLY;
975 }
976 else
977 rc = VERR_VDI_NOT_OPENED;
978
979 LogFlowFunc(("returns %Vrc\n", rc));
980 return rc;
981}
982
983/** @copydoc VBOXHDDBACKEND::pfnDump */
984static void rawDump(void *pBackendData)
985{
986 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
987
988 Assert(pImage);
989 if (pImage)
990 {
991 RTLogPrintf("Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
992 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
993 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
994 pImage->cbSize / 512);
995 }
996}
997
998static int rawGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
999{
1000 int rc = VERR_NOT_IMPLEMENTED;
1001 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc));
1002 return rc;
1003}
1004
1005static int rawGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
1006{
1007 int rc = VERR_NOT_IMPLEMENTED;
1008 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc));
1009 return rc;
1010}
1011
1012static int rawSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
1013{
1014 int rc = VERR_NOT_IMPLEMENTED;
1015 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc));
1016 return rc;
1017}
1018
1019static int rawGetParentFilename(void *pvBackendData, char **ppszParentFilename)
1020{
1021 int rc = VERR_NOT_IMPLEMENTED;
1022 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc));
1023 return rc;
1024}
1025
1026static int rawSetParentFilename(void *pvBackendData, const char *pszParentFilename)
1027{
1028 int rc = VERR_NOT_IMPLEMENTED;
1029 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc));
1030 return rc;
1031}
1032
1033static bool rawIsAsyncIOSupported(void *pvBackendData)
1034{
1035 return false;
1036}
1037
1038static int rawAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
1039 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
1040{
1041 int rc = VERR_NOT_IMPLEMENTED;
1042 LogFlowFunc(("returns %Vrc\n", rc));
1043 return rc;
1044}
1045
1046static int rawAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
1047 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
1048{
1049 int rc = VERR_NOT_IMPLEMENTED;
1050 LogFlowFunc(("returns %Vrc\n", rc));
1051 return rc;
1052}
1053
1054VBOXHDDBACKEND g_RawBackend =
1055{
1056 /* pszBackendName */
1057 "raw",
1058 /* cbSize */
1059 sizeof(VBOXHDDBACKEND),
1060 /* uBackendCaps */
1061 VD_CAP_CREATE_FIXED | VD_CAP_FILE,
1062 /* pfnCheckIfValid */
1063 rawCheckIfValid,
1064 /* pfnOpen */
1065 rawOpen,
1066 /* pfnCreate */
1067 rawCreate,
1068 /* pfnRename */
1069 rawRename,
1070 /* pfnClose */
1071 rawClose,
1072 /* pfnRead */
1073 rawRead,
1074 /* pfnWrite */
1075 rawWrite,
1076 /* pfnFlush */
1077 rawFlush,
1078 /* pfnGetVersion */
1079 rawGetVersion,
1080 /* pfnGetImageType */
1081 rawGetImageType,
1082 /* pfnGetSize */
1083 rawGetSize,
1084 /* pfnGetFileSize */
1085 rawGetFileSize,
1086 /* pfnGetPCHSGeometry */
1087 rawGetPCHSGeometry,
1088 /* pfnSetPCHSGeometry */
1089 rawSetPCHSGeometry,
1090 /* pfnGetLCHSGeometry */
1091 rawGetLCHSGeometry,
1092 /* pfnSetLCHSGeometry */
1093 rawSetLCHSGeometry,
1094 /* pfnGetImageFlags */
1095 rawGetImageFlags,
1096 /* pfnGetOpenFlags */
1097 rawGetOpenFlags,
1098 /* pfnSetOpenFlags */
1099 rawSetOpenFlags,
1100 /* pfnGetComment */
1101 rawGetComment,
1102 /* pfnSetComment */
1103 rawSetComment,
1104 /* pfnGetUuid */
1105 rawGetUuid,
1106 /* pfnSetUuid */
1107 rawSetUuid,
1108 /* pfnGetModificationUuid */
1109 rawGetModificationUuid,
1110 /* pfnSetModificationUuid */
1111 rawSetModificationUuid,
1112 /* pfnGetParentUuid */
1113 rawGetParentUuid,
1114 /* pfnSetParentUuid */
1115 rawSetParentUuid,
1116 /* pfnGetParentModificationUuid */
1117 rawGetParentModificationUuid,
1118 /* pfnSetParentModificationUuid */
1119 rawSetParentModificationUuid,
1120 /* pfnDump */
1121 rawDump,
1122 /* pfnGetTimeStamp */
1123 rawGetTimeStamp,
1124 /* pfnGetParentTimeStamp */
1125 rawGetParentTimeStamp,
1126 /* pfnSetParentTimeStamp */
1127 rawSetParentTimeStamp,
1128 /* pfnGetParentFilename */
1129 rawGetParentFilename,
1130 /* pfnSetParentFilename */
1131 rawSetParentFilename,
1132 /* pfnIsAsyncIOSupported */
1133 rawIsAsyncIOSupported,
1134 /* pfnAsyncRead */
1135 rawAsyncRead,
1136 /* pfnAsyncWrite */
1137 rawAsyncWrite
1138};
1139
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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