VirtualBox

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

Last change on this file since 9113 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

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