VirtualBox

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

Last change on this file since 8110 was 7780, checked in by vboxsync, 17 years ago

Add function to query all available VD backends, together with their capabilities. Also added a flag to the write operation (purely a dummy at the moment).

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

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