VirtualBox

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

Last change on this file since 33223 was 33182, checked in by vboxsync, 14 years ago

Devices/Storage: implement sequential reading of streamOptimized VMDK images

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette