VirtualBox

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

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

Storage/VBoxHDD-new: Add information about configuration settings supported by a backend.
Storage/iSCSI: Move initiator name default to backend.
Main: Move iSCSI initiator name default to backend.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.2 KB
Line 
1/** $Id: RawHDDCore.cpp 11484 2008-08-19 12:41:38Z 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 /** 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 pfnProgress = pCbProgress->pfnProgress;
399 pvUser = pIfProgress->pvUser;
400 }
401
402 /* Check open flags. All valid flags are supported. */
403 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
404 {
405 rc = VERR_INVALID_PARAMETER;
406 goto out;
407 }
408
409 /* Check remaining arguments. */
410 if ( !VALID_PTR(pszFilename)
411 || !*pszFilename
412 || (enmType != VD_IMAGE_TYPE_FIXED)
413 || !VALID_PTR(pPCHSGeometry)
414 || !VALID_PTR(pLCHSGeometry))
415 {
416 rc = VERR_INVALID_PARAMETER;
417 goto out;
418 }
419
420 pImage = (PRAWIMAGE)RTMemAllocZ(sizeof(RAWIMAGE));
421 if (!pImage)
422 {
423 rc = VERR_NO_MEMORY;
424 goto out;
425 }
426 pImage->pszFilename = pszFilename;
427 pImage->File = NIL_RTFILE;
428 pImage->pVDIfsDisk = pVDIfsDisk;
429
430 rc = rawCreateImage(pImage, enmType, cbSize, uImageFlags, pszComment,
431 pPCHSGeometry, pLCHSGeometry,
432 pfnProgress, pvUser, uPercentStart, uPercentSpan);
433 if (RT_SUCCESS(rc))
434 {
435 /* So far the image is opened in read/write mode. Make sure the
436 * image is opened in read-only mode if the caller requested that. */
437 if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
438 {
439 rawFreeImage(pImage, false);
440 rc = rawOpenImage(pImage, uOpenFlags);
441 if (RT_FAILURE(rc))
442 goto out;
443 }
444 *ppBackendData = pImage;
445 }
446
447out:
448 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
449 return rc;
450}
451
452/** @copydoc VBOXHDDBACKEND::pfnRename */
453static int rawRename(void *pBackendData, const char *pszFilename)
454{
455 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
456 int rc = VERR_NOT_IMPLEMENTED;
457
458 LogFlowFunc(("returns %Rrc\n", rc));
459 return rc;
460}
461
462/** @copydoc VBOXHDDBACKEND::pfnClose */
463static int rawClose(void *pBackendData, bool fDelete)
464{
465 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
466 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
467 int rc = VINF_SUCCESS;
468
469 /* Freeing a never allocated image (e.g. because the open failed) is
470 * not signalled as an error. After all nothing bad happens. */
471 if (pImage)
472 rawFreeImage(pImage, fDelete);
473
474 LogFlowFunc(("returns %Rrc\n", rc));
475 return rc;
476}
477
478/** @copydoc VBOXHDDBACKEND::pfnRead */
479static int rawRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
480 size_t cbToRead, size_t *pcbActuallyRead)
481{
482 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
483 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
484 int rc;
485
486 Assert(pImage);
487 Assert(uOffset % 512 == 0);
488 Assert(cbToRead % 512 == 0);
489
490 if ( uOffset + cbToRead > pImage->cbSize
491 || cbToRead == 0)
492 {
493 rc = VERR_INVALID_PARAMETER;
494 goto out;
495 }
496
497 rc = RTFileReadAt(pImage->File, uOffset, pvBuf, cbToRead, NULL);
498 *pcbActuallyRead = cbToRead;
499
500out:
501 LogFlowFunc(("returns %Rrc\n", rc));
502 return rc;
503}
504
505/** @copydoc VBOXHDDBACKEND::pfnWrite */
506static int rawWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
507 size_t cbToWrite, size_t *pcbWriteProcess,
508 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
509{
510 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
511 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
512 int rc;
513
514 Assert(pImage);
515 Assert(uOffset % 512 == 0);
516 Assert(cbToWrite % 512 == 0);
517
518 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
519 {
520 rc = VERR_VDI_IMAGE_READ_ONLY;
521 goto out;
522 }
523
524 if ( uOffset + cbToWrite > pImage->cbSize
525 || cbToWrite == 0)
526 {
527 rc = VERR_INVALID_PARAMETER;
528 goto out;
529 }
530
531 rc = RTFileWriteAt(pImage->File, uOffset, pvBuf, cbToWrite, NULL);
532 if (pcbWriteProcess)
533 *pcbWriteProcess = cbToWrite;
534
535out:
536 LogFlowFunc(("returns %Rrc\n", rc));
537 return rc;
538}
539
540/** @copydoc VBOXHDDBACKEND::pfnFlush */
541static int rawFlush(void *pBackendData)
542{
543 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
544 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
545 int rc;
546
547 rc = rawFlushImage(pImage);
548 LogFlowFunc(("returns %Rrc\n", rc));
549 return rc;
550}
551
552/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
553static unsigned rawGetVersion(void *pBackendData)
554{
555 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
556 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
557
558 Assert(pImage);
559
560 if (pImage)
561 return 1;
562 else
563 return 0;
564}
565
566/** @copydoc VBOXHDDBACKEND::pfnGetImageType */
567static int rawGetImageType(void *pBackendData, PVDIMAGETYPE penmImageType)
568{
569 LogFlowFunc(("pBackendData=%#p penmImageType=%#p\n", pBackendData, penmImageType));
570 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
571 int rc = VINF_SUCCESS;
572
573 Assert(pImage);
574 Assert(penmImageType);
575
576 if (pImage)
577 *penmImageType = pImage->enmImageType;
578 else
579 rc = VERR_VDI_NOT_OPENED;
580
581 LogFlowFunc(("returns %Rrc enmImageType=%u\n", rc, *penmImageType));
582 return rc;
583}
584
585/** @copydoc VBOXHDDBACKEND::pfnGetSize */
586static uint64_t rawGetSize(void *pBackendData)
587{
588 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
589 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
590
591 Assert(pImage);
592
593 if (pImage)
594 return pImage->cbSize;
595 else
596 return 0;
597}
598
599/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
600static uint64_t rawGetFileSize(void *pBackendData)
601{
602 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
603 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
604 uint64_t cb = 0;
605
606 Assert(pImage);
607
608 if (pImage)
609 {
610 uint64_t cbFile;
611 if (pImage->File != NIL_RTFILE)
612 {
613 int rc = RTFileGetSize(pImage->File, &cbFile);
614 if (RT_SUCCESS(rc))
615 cb += cbFile;
616 }
617 }
618
619 LogFlowFunc(("returns %lld\n", cb));
620 return cb;
621}
622
623/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
624static int rawGetPCHSGeometry(void *pBackendData,
625 PPDMMEDIAGEOMETRY pPCHSGeometry)
626{
627 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
628 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
629 int rc;
630
631 Assert(pImage);
632
633 if (pImage)
634 {
635 if (pImage->PCHSGeometry.cCylinders)
636 {
637 *pPCHSGeometry = pImage->PCHSGeometry;
638 rc = VINF_SUCCESS;
639 }
640 else
641 rc = VERR_VDI_GEOMETRY_NOT_SET;
642 }
643 else
644 rc = VERR_VDI_NOT_OPENED;
645
646 LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
647 return rc;
648}
649
650/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
651static int rawSetPCHSGeometry(void *pBackendData,
652 PCPDMMEDIAGEOMETRY pPCHSGeometry)
653{
654 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
655 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
656 int rc;
657
658 Assert(pImage);
659
660 if (pImage)
661 {
662 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
663 {
664 rc = VERR_VDI_IMAGE_READ_ONLY;
665 goto out;
666 }
667
668 pImage->PCHSGeometry = *pPCHSGeometry;
669 rc = VINF_SUCCESS;
670 }
671 else
672 rc = VERR_VDI_NOT_OPENED;
673
674out:
675 LogFlowFunc(("returns %Rrc\n", rc));
676 return rc;
677}
678
679/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
680static int rawGetLCHSGeometry(void *pBackendData,
681 PPDMMEDIAGEOMETRY pLCHSGeometry)
682{
683 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
684 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
685 int rc;
686
687 Assert(pImage);
688
689 if (pImage)
690 {
691 if (pImage->LCHSGeometry.cCylinders)
692 {
693 *pLCHSGeometry = pImage->LCHSGeometry;
694 rc = VINF_SUCCESS;
695 }
696 else
697 rc = VERR_VDI_GEOMETRY_NOT_SET;
698 }
699 else
700 rc = VERR_VDI_NOT_OPENED;
701
702 LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
703 return rc;
704}
705
706/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
707static int rawSetLCHSGeometry(void *pBackendData,
708 PCPDMMEDIAGEOMETRY pLCHSGeometry)
709{
710 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
711 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
712 int rc;
713
714 Assert(pImage);
715
716 if (pImage)
717 {
718 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
719 {
720 rc = VERR_VDI_IMAGE_READ_ONLY;
721 goto out;
722 }
723
724 pImage->LCHSGeometry = *pLCHSGeometry;
725 rc = VINF_SUCCESS;
726 }
727 else
728 rc = VERR_VDI_NOT_OPENED;
729
730out:
731 LogFlowFunc(("returns %Rrc\n", rc));
732 return rc;
733}
734
735/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
736static unsigned rawGetImageFlags(void *pBackendData)
737{
738 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
739 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
740 unsigned uImageFlags;
741
742 Assert(pImage);
743
744 if (pImage)
745 uImageFlags = pImage->uImageFlags;
746 else
747 uImageFlags = 0;
748
749 LogFlowFunc(("returns %#x\n", uImageFlags));
750 return uImageFlags;
751}
752
753/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
754static unsigned rawGetOpenFlags(void *pBackendData)
755{
756 LogFlowFunc(("pBackendData=%#p\n", pBackendData));
757 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
758 unsigned uOpenFlags;
759
760 Assert(pImage);
761
762 if (pImage)
763 uOpenFlags = pImage->uOpenFlags;
764 else
765 uOpenFlags = 0;
766
767 LogFlowFunc(("returns %#x\n", uOpenFlags));
768 return uOpenFlags;
769}
770
771/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
772static int rawSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
773{
774 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
775 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
776 int rc;
777
778 /* Image must be opened and the new flags must be valid. Just readonly flag
779 * is supported. */
780 if (!pImage || uOpenFlags & ~VD_OPEN_FLAGS_READONLY)
781 {
782 rc = VERR_INVALID_PARAMETER;
783 goto out;
784 }
785
786 /* Implement this operation via reopening the image. */
787 rawFreeImage(pImage, false);
788 rc = rawOpenImage(pImage, uOpenFlags);
789
790out:
791 LogFlowFunc(("returns %Rrc\n", rc));
792 return rc;
793}
794
795/** @copydoc VBOXHDDBACKEND::pfnGetComment */
796static int rawGetComment(void *pBackendData, char *pszComment,
797 size_t cbComment)
798{
799 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
800 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
801 int rc;
802
803 Assert(pImage);
804
805 if (pImage)
806 {
807 if (pszComment)
808 *pszComment = '\0';
809 rc = VINF_SUCCESS;
810 }
811 else
812 rc = VERR_VDI_NOT_OPENED;
813
814 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
815 return rc;
816}
817
818/** @copydoc VBOXHDDBACKEND::pfnSetComment */
819static int rawSetComment(void *pBackendData, const char *pszComment)
820{
821 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
822 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
823 int rc;
824
825 Assert(pImage);
826
827 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
828 {
829 rc = VERR_VDI_IMAGE_READ_ONLY;
830 goto out;
831 }
832
833 if (pImage)
834 rc = VERR_NOT_SUPPORTED;
835 else
836 rc = VERR_VDI_NOT_OPENED;
837
838out:
839 LogFlowFunc(("returns %Rrc\n", rc));
840 return rc;
841}
842
843/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
844static int rawGetUuid(void *pBackendData, PRTUUID pUuid)
845{
846 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
847 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
848 int rc;
849
850 Assert(pImage);
851
852 if (pImage)
853 rc = VERR_NOT_SUPPORTED;
854 else
855 rc = VERR_VDI_NOT_OPENED;
856
857 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
858 return rc;
859}
860
861/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
862static int rawSetUuid(void *pBackendData, PCRTUUID pUuid)
863{
864 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
865 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
866 int rc;
867
868 LogFlowFunc(("%RTuuid\n", pUuid));
869 Assert(pImage);
870
871 if (pImage)
872 {
873 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
874 rc = VERR_NOT_SUPPORTED;
875 else
876 rc = VERR_VDI_IMAGE_READ_ONLY;
877 }
878 else
879 rc = VERR_VDI_NOT_OPENED;
880
881 LogFlowFunc(("returns %Rrc\n", rc));
882 return rc;
883}
884
885/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
886static int rawGetModificationUuid(void *pBackendData, PRTUUID pUuid)
887{
888 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
889 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
890 int rc;
891
892 Assert(pImage);
893
894 if (pImage)
895 rc = VERR_NOT_SUPPORTED;
896 else
897 rc = VERR_VDI_NOT_OPENED;
898
899 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
900 return rc;
901}
902
903/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
904static int rawSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
905{
906 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
907 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
908 int rc;
909
910 Assert(pImage);
911
912 if (pImage)
913 {
914 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
915 rc = VERR_NOT_SUPPORTED;
916 else
917 rc = VERR_VDI_IMAGE_READ_ONLY;
918 }
919 else
920 rc = VERR_VDI_NOT_OPENED;
921
922 LogFlowFunc(("returns %Rrc\n", rc));
923 return rc;
924}
925
926/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
927static int rawGetParentUuid(void *pBackendData, PRTUUID pUuid)
928{
929 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
930 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
931 int rc;
932
933 Assert(pImage);
934
935 if (pImage)
936 rc = VERR_NOT_SUPPORTED;
937 else
938 rc = VERR_VDI_NOT_OPENED;
939
940 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
941 return rc;
942}
943
944/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
945static int rawSetParentUuid(void *pBackendData, PCRTUUID pUuid)
946{
947 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
948 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
949 int rc;
950
951 Assert(pImage);
952
953 if (pImage)
954 {
955 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
956 rc = VERR_NOT_SUPPORTED;
957 else
958 rc = VERR_VDI_IMAGE_READ_ONLY;
959 }
960 else
961 rc = VERR_VDI_NOT_OPENED;
962
963 LogFlowFunc(("returns %Rrc\n", rc));
964 return rc;
965}
966
967/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
968static int rawGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
969{
970 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
971 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
972 int rc;
973
974 Assert(pImage);
975
976 if (pImage)
977 rc = VERR_NOT_SUPPORTED;
978 else
979 rc = VERR_VDI_NOT_OPENED;
980
981 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
982 return rc;
983}
984
985/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
986static int rawSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
987{
988 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
989 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
990 int rc;
991
992 Assert(pImage);
993
994 if (pImage)
995 {
996 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
997 rc = VERR_NOT_SUPPORTED;
998 else
999 rc = VERR_VDI_IMAGE_READ_ONLY;
1000 }
1001 else
1002 rc = VERR_VDI_NOT_OPENED;
1003
1004 LogFlowFunc(("returns %Rrc\n", rc));
1005 return rc;
1006}
1007
1008/** @copydoc VBOXHDDBACKEND::pfnDump */
1009static void rawDump(void *pBackendData)
1010{
1011 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1012
1013 Assert(pImage);
1014 if (pImage)
1015 {
1016 RTLogPrintf("Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
1017 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
1018 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
1019 pImage->cbSize / 512);
1020 }
1021}
1022
1023static int rawGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
1024{
1025 int rc = VERR_NOT_IMPLEMENTED;
1026 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1027 return rc;
1028}
1029
1030static int rawGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
1031{
1032 int rc = VERR_NOT_IMPLEMENTED;
1033 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1034 return rc;
1035}
1036
1037static int rawSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
1038{
1039 int rc = VERR_NOT_IMPLEMENTED;
1040 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1041 return rc;
1042}
1043
1044static int rawGetParentFilename(void *pvBackendData, char **ppszParentFilename)
1045{
1046 int rc = VERR_NOT_IMPLEMENTED;
1047 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1048 return rc;
1049}
1050
1051static int rawSetParentFilename(void *pvBackendData, const char *pszParentFilename)
1052{
1053 int rc = VERR_NOT_IMPLEMENTED;
1054 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
1055 return rc;
1056}
1057
1058static bool rawIsAsyncIOSupported(void *pvBackendData)
1059{
1060 return false;
1061}
1062
1063static int rawAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
1064 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
1065{
1066 int rc = VERR_NOT_IMPLEMENTED;
1067 LogFlowFunc(("returns %Rrc\n", rc));
1068 return rc;
1069}
1070
1071static int rawAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
1072 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
1073{
1074 int rc = VERR_NOT_IMPLEMENTED;
1075 LogFlowFunc(("returns %Rrc\n", rc));
1076 return rc;
1077}
1078
1079VBOXHDDBACKEND g_RawBackend =
1080{
1081 /* pszBackendName */
1082 "raw",
1083 /* cbSize */
1084 sizeof(VBOXHDDBACKEND),
1085 /* uBackendCaps */
1086 VD_CAP_CREATE_FIXED | VD_CAP_FILE,
1087 /* papszFileExtensions */
1088 s_apszRawFileExtensions,
1089 /* paConfigInfo */
1090 NULL,
1091 /* pfnCheckIfValid */
1092 rawCheckIfValid,
1093 /* pfnOpen */
1094 rawOpen,
1095 /* pfnCreate */
1096 rawCreate,
1097 /* pfnRename */
1098 rawRename,
1099 /* pfnClose */
1100 rawClose,
1101 /* pfnRead */
1102 rawRead,
1103 /* pfnWrite */
1104 rawWrite,
1105 /* pfnFlush */
1106 rawFlush,
1107 /* pfnGetVersion */
1108 rawGetVersion,
1109 /* pfnGetImageType */
1110 rawGetImageType,
1111 /* pfnGetSize */
1112 rawGetSize,
1113 /* pfnGetFileSize */
1114 rawGetFileSize,
1115 /* pfnGetPCHSGeometry */
1116 rawGetPCHSGeometry,
1117 /* pfnSetPCHSGeometry */
1118 rawSetPCHSGeometry,
1119 /* pfnGetLCHSGeometry */
1120 rawGetLCHSGeometry,
1121 /* pfnSetLCHSGeometry */
1122 rawSetLCHSGeometry,
1123 /* pfnGetImageFlags */
1124 rawGetImageFlags,
1125 /* pfnGetOpenFlags */
1126 rawGetOpenFlags,
1127 /* pfnSetOpenFlags */
1128 rawSetOpenFlags,
1129 /* pfnGetComment */
1130 rawGetComment,
1131 /* pfnSetComment */
1132 rawSetComment,
1133 /* pfnGetUuid */
1134 rawGetUuid,
1135 /* pfnSetUuid */
1136 rawSetUuid,
1137 /* pfnGetModificationUuid */
1138 rawGetModificationUuid,
1139 /* pfnSetModificationUuid */
1140 rawSetModificationUuid,
1141 /* pfnGetParentUuid */
1142 rawGetParentUuid,
1143 /* pfnSetParentUuid */
1144 rawSetParentUuid,
1145 /* pfnGetParentModificationUuid */
1146 rawGetParentModificationUuid,
1147 /* pfnSetParentModificationUuid */
1148 rawSetParentModificationUuid,
1149 /* pfnDump */
1150 rawDump,
1151 /* pfnGetTimeStamp */
1152 rawGetTimeStamp,
1153 /* pfnGetParentTimeStamp */
1154 rawGetParentTimeStamp,
1155 /* pfnSetParentTimeStamp */
1156 rawSetParentTimeStamp,
1157 /* pfnGetParentFilename */
1158 rawGetParentFilename,
1159 /* pfnSetParentFilename */
1160 rawSetParentFilename,
1161 /* pfnIsAsyncIOSupported */
1162 rawIsAsyncIOSupported,
1163 /* pfnAsyncRead */
1164 rawAsyncRead,
1165 /* pfnAsyncWrite */
1166 rawAsyncWrite
1167};
1168
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