VirtualBox

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

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

Storage: Eradicated the last bits using the old VDI only backend, keeping only the testcases for now (no longer built).

Completely removed old iSCSI driver.

Added intnet option to addiscsidisk and adjusted documentation.

Made backend name comparisons case-insensitive.

Detect VMDK files not according to VMDK 1.0 and reject with clear error message.

Changed format probing logic to not fall through to the "unsupported" case if it's a known format, i.e. has valid header.

VBoxManage converthd generic format converter made official.

Added format flag to VBoxManage createhd, allows creating VMDK files.

VBoxManage convertdd reimplemented based on new framework, supporting any image format.

VBoxManage internalcommands sethduuid reimplemented based on new framework, supporting any image format.

Cleaned up error codes.

  • 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 15366 2008-12-12 13:50:32Z 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_VD_RAW_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_VD_RAW_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_VD_RAW_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_VD_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_VD_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_VD_GEOMETRY_NOT_SET;
643 }
644 else
645 rc = VERR_VD_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_VD_IMAGE_READ_ONLY;
666 goto out;
667 }
668
669 pImage->PCHSGeometry = *pPCHSGeometry;
670 rc = VINF_SUCCESS;
671 }
672 else
673 rc = VERR_VD_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_VD_GEOMETRY_NOT_SET;
699 }
700 else
701 rc = VERR_VD_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_VD_IMAGE_READ_ONLY;
722 goto out;
723 }
724
725 pImage->LCHSGeometry = *pLCHSGeometry;
726 rc = VINF_SUCCESS;
727 }
728 else
729 rc = VERR_VD_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_VD_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_VD_IMAGE_READ_ONLY;
831 goto out;
832 }
833
834 if (pImage)
835 rc = VERR_NOT_SUPPORTED;
836 else
837 rc = VERR_VD_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_VD_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_VD_IMAGE_READ_ONLY;
878 }
879 else
880 rc = VERR_VD_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_VD_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_VD_IMAGE_READ_ONLY;
919 }
920 else
921 rc = VERR_VD_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_VD_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_VD_IMAGE_READ_ONLY;
960 }
961 else
962 rc = VERR_VD_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_VD_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_VD_IMAGE_READ_ONLY;
1001 }
1002 else
1003 rc = VERR_VD_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