VirtualBox

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

Last change on this file since 15164 was 14967, checked in by vboxsync, 16 years ago

#3162: Another attempt to introduce compose name and location callbacks, better version of r40315.

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