VirtualBox

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

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

Storage/Raw: fix crash when creating failed

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