VirtualBox

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

Last change on this file since 33000 was 32598, checked in by vboxsync, 14 years ago

Storage/iSCSI+Raw+VMDK: fix incorrect error code returned by pfnCheckIfValid, triggered severe regression in the snapshot code

  • 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 32598 2010-09-17 12:36:19Z 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. Just readonly and
929 * info flags are supported. */
930 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)))
931 {
932 rc = VERR_INVALID_PARAMETER;
933 goto out;
934 }
935
936 /* Implement this operation via reopening the image. */
937 rc = rawFreeImage(pImage, false);
938 if (RT_FAILURE(rc))
939 goto out;
940 rc = rawOpenImage(pImage, uOpenFlags);
941
942out:
943 LogFlowFunc(("returns %Rrc\n", rc));
944 return rc;
945}
946
947/** @copydoc VBOXHDDBACKEND::pfnGetComment */
948static int rawGetComment(void *pBackendData, char *pszComment,
949 size_t cbComment)
950{
951 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
952 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
953 int rc;
954
955 AssertPtr(pImage);
956
957 if (pImage)
958 rc = VERR_NOT_SUPPORTED;
959 else
960 rc = VERR_VD_NOT_OPENED;
961
962 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
963 return rc;
964}
965
966/** @copydoc VBOXHDDBACKEND::pfnSetComment */
967static int rawSetComment(void *pBackendData, const char *pszComment)
968{
969 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
970 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
971 int rc;
972
973 AssertPtr(pImage);
974
975 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
976 {
977 rc = VERR_VD_IMAGE_READ_ONLY;
978 goto out;
979 }
980
981 if (pImage)
982 rc = VERR_NOT_SUPPORTED;
983 else
984 rc = VERR_VD_NOT_OPENED;
985
986out:
987 LogFlowFunc(("returns %Rrc\n", rc));
988 return rc;
989}
990
991/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
992static int rawGetUuid(void *pBackendData, PRTUUID pUuid)
993{
994 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
995 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
996 int rc;
997
998 AssertPtr(pImage);
999
1000 if (pImage)
1001 rc = VERR_NOT_SUPPORTED;
1002 else
1003 rc = VERR_VD_NOT_OPENED;
1004
1005 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1006 return rc;
1007}
1008
1009/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
1010static int rawSetUuid(void *pBackendData, PCRTUUID pUuid)
1011{
1012 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1013 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1014 int rc;
1015
1016 LogFlowFunc(("%RTuuid\n", pUuid));
1017 AssertPtr(pImage);
1018
1019 if (pImage)
1020 {
1021 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1022 rc = VERR_NOT_SUPPORTED;
1023 else
1024 rc = VERR_VD_IMAGE_READ_ONLY;
1025 }
1026 else
1027 rc = VERR_VD_NOT_OPENED;
1028
1029 LogFlowFunc(("returns %Rrc\n", rc));
1030 return rc;
1031}
1032
1033/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
1034static int rawGetModificationUuid(void *pBackendData, PRTUUID pUuid)
1035{
1036 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1037 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1038 int rc;
1039
1040 AssertPtr(pImage);
1041
1042 if (pImage)
1043 rc = VERR_NOT_SUPPORTED;
1044 else
1045 rc = VERR_VD_NOT_OPENED;
1046
1047 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1048 return rc;
1049}
1050
1051/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
1052static int rawSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
1053{
1054 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1055 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1056 int rc;
1057
1058 AssertPtr(pImage);
1059
1060 if (pImage)
1061 {
1062 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1063 rc = VERR_NOT_SUPPORTED;
1064 else
1065 rc = VERR_VD_IMAGE_READ_ONLY;
1066 }
1067 else
1068 rc = VERR_VD_NOT_OPENED;
1069
1070 LogFlowFunc(("returns %Rrc\n", rc));
1071 return rc;
1072}
1073
1074/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
1075static int rawGetParentUuid(void *pBackendData, PRTUUID pUuid)
1076{
1077 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1078 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1079 int rc;
1080
1081 AssertPtr(pImage);
1082
1083 if (pImage)
1084 rc = VERR_NOT_SUPPORTED;
1085 else
1086 rc = VERR_VD_NOT_OPENED;
1087
1088 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1089 return rc;
1090}
1091
1092/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
1093static int rawSetParentUuid(void *pBackendData, PCRTUUID pUuid)
1094{
1095 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1096 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1097 int rc;
1098
1099 AssertPtr(pImage);
1100
1101 if (pImage)
1102 {
1103 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1104 rc = VERR_NOT_SUPPORTED;
1105 else
1106 rc = VERR_VD_IMAGE_READ_ONLY;
1107 }
1108 else
1109 rc = VERR_VD_NOT_OPENED;
1110
1111 LogFlowFunc(("returns %Rrc\n", rc));
1112 return rc;
1113}
1114
1115/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
1116static int rawGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
1117{
1118 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
1119 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1120 int rc;
1121
1122 AssertPtr(pImage);
1123
1124 if (pImage)
1125 rc = VERR_NOT_SUPPORTED;
1126 else
1127 rc = VERR_VD_NOT_OPENED;
1128
1129 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
1130 return rc;
1131}
1132
1133/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
1134static int rawSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
1135{
1136 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
1137 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1138 int rc;
1139
1140 AssertPtr(pImage);
1141
1142 if (pImage)
1143 {
1144 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1145 rc = VERR_NOT_SUPPORTED;
1146 else
1147 rc = VERR_VD_IMAGE_READ_ONLY;
1148 }
1149 else
1150 rc = VERR_VD_NOT_OPENED;
1151
1152 LogFlowFunc(("returns %Rrc\n", rc));
1153 return rc;
1154}
1155
1156/** @copydoc VBOXHDDBACKEND::pfnDump */
1157static void rawDump(void *pBackendData)
1158{
1159 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1160
1161 AssertPtr(pImage);
1162 if (pImage)
1163 {
1164 rawMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
1165 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
1166 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
1167 pImage->cbSize / 512);
1168 }
1169}
1170
1171/** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */
1172static bool rawIsAsyncIOSupported(void *pBackendData)
1173{
1174 return true;
1175}
1176
1177/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
1178static int rawAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
1179 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
1180{
1181 int rc = VINF_SUCCESS;
1182 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1183
1184 rc = rawFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead);
1185 if (RT_SUCCESS(rc))
1186 *pcbActuallyRead = cbRead;
1187
1188 return rc;
1189}
1190
1191/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
1192static int rawAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
1193 PVDIOCTX pIoCtx,
1194 size_t *pcbWriteProcess, size_t *pcbPreRead,
1195 size_t *pcbPostRead, unsigned fWrite)
1196{
1197 int rc = VINF_SUCCESS;
1198 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1199
1200 rc = rawFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL);
1201 if (RT_SUCCESS(rc))
1202 {
1203 *pcbWriteProcess = cbWrite;
1204 *pcbPostRead = 0;
1205 *pcbPreRead = 0;
1206 }
1207
1208 return rc;
1209}
1210
1211/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
1212static int rawAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
1213{
1214 int rc = VINF_SUCCESS;
1215 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
1216
1217 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
1218 rc = rawFileFlushAsync(pImage, pIoCtx, NULL, NULL);
1219
1220 return rc;
1221}
1222
1223
1224VBOXHDDBACKEND g_RawBackend =
1225{
1226 /* pszBackendName */
1227 "raw",
1228 /* cbSize */
1229 sizeof(VBOXHDDBACKEND),
1230 /* uBackendCaps */
1231 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
1232 /* papszFileExtensions */
1233 s_apszRawFileExtensions,
1234 /* paConfigInfo */
1235 NULL,
1236 /* hPlugin */
1237 NIL_RTLDRMOD,
1238 /* pfnCheckIfValid */
1239 rawCheckIfValid,
1240 /* pfnOpen */
1241 rawOpen,
1242 /* pfnCreate */
1243 rawCreate,
1244 /* pfnRename */
1245 rawRename,
1246 /* pfnClose */
1247 rawClose,
1248 /* pfnRead */
1249 rawRead,
1250 /* pfnWrite */
1251 rawWrite,
1252 /* pfnFlush */
1253 rawFlush,
1254 /* pfnGetVersion */
1255 rawGetVersion,
1256 /* pfnGetSize */
1257 rawGetSize,
1258 /* pfnGetFileSize */
1259 rawGetFileSize,
1260 /* pfnGetPCHSGeometry */
1261 rawGetPCHSGeometry,
1262 /* pfnSetPCHSGeometry */
1263 rawSetPCHSGeometry,
1264 /* pfnGetLCHSGeometry */
1265 rawGetLCHSGeometry,
1266 /* pfnSetLCHSGeometry */
1267 rawSetLCHSGeometry,
1268 /* pfnGetImageFlags */
1269 rawGetImageFlags,
1270 /* pfnGetOpenFlags */
1271 rawGetOpenFlags,
1272 /* pfnSetOpenFlags */
1273 rawSetOpenFlags,
1274 /* pfnGetComment */
1275 rawGetComment,
1276 /* pfnSetComment */
1277 rawSetComment,
1278 /* pfnGetUuid */
1279 rawGetUuid,
1280 /* pfnSetUuid */
1281 rawSetUuid,
1282 /* pfnGetModificationUuid */
1283 rawGetModificationUuid,
1284 /* pfnSetModificationUuid */
1285 rawSetModificationUuid,
1286 /* pfnGetParentUuid */
1287 rawGetParentUuid,
1288 /* pfnSetParentUuid */
1289 rawSetParentUuid,
1290 /* pfnGetParentModificationUuid */
1291 rawGetParentModificationUuid,
1292 /* pfnSetParentModificationUuid */
1293 rawSetParentModificationUuid,
1294 /* pfnDump */
1295 rawDump,
1296 /* pfnGetTimeStamp */
1297 NULL,
1298 /* pfnGetParentTimeStamp */
1299 NULL,
1300 /* pfnSetParentTimeStamp */
1301 NULL,
1302 /* pfnGetParentFilename */
1303 NULL,
1304 /* pfnSetParentFilename */
1305 NULL,
1306 /* pfnIsAsyncIOSupported */
1307 rawIsAsyncIOSupported,
1308 /* pfnAsyncRead */
1309 rawAsyncRead,
1310 /* pfnAsyncWrite */
1311 rawAsyncWrite,
1312 /* pfnAsyncFlush */
1313 rawAsyncFlush,
1314 /* pfnComposeLocation */
1315 genericFileComposeLocation,
1316 /* pfnComposeName */
1317 genericFileComposeName,
1318 /* pfnCompact */
1319 NULL,
1320 /* pfnResize */
1321 NULL
1322};
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use