Changeset 47345 in vbox
- Timestamp:
- Jul 23, 2013 3:29:30 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 87490
- Location:
- trunk
- Files:
-
- 3 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vd-ifs.h
r44529 r47345 604 604 return pIfIo->pfnFlushSync(pIfIo->Core.pvUser, pStorage); 605 605 } 606 607 /** 608 * Create a VFS stream handle around a VD I/O interface. 609 * 610 * The I/O interface will not be closed or free by the stream, the caller will 611 * do so after it is done with the stream and has released the instances of the 612 * I/O stream object returned by this API. 613 * 614 * @return VBox status code. 615 * @param pVDIfsIo Pointer to the VD I/O interface. 616 * @param fFlags RTFILE_O_XXX, access mask requied. 617 * @param phVfsIos Where to return the VFS I/O stream handle on 618 * success. 619 */ 620 VBOXDDU_DECL(int) VDIfCreateVfsStream(PVDINTERFACEIO pVDIfsIo, uint32_t fFlags, PRTVFSIOSTREAM phVfsIos); 621 606 622 607 623 /** -
trunk/include/VBox/vd.h
r44408 r47345 1248 1248 * @param pDisk Pointer to HDD container. 1249 1249 * @param fFlags Combination of the VD_VFSFILE_* flags. 1250 * @param phVfsFile Where to stoer the handle to the VFS file on success. 1250 * @param phVfsFile Where to store the handle to the VFS file on 1251 * success. 1251 1252 */ 1252 1253 VBOXDDU_DECL(int) VDCreateVfsFileFromDisk(PVBOXHDD pDisk, uint32_t fFlags, -
trunk/src/VBox/Storage/Makefile.kmk
r41576 r47345 38 38 VD.cpp \ 39 39 VDVfs.cpp \ 40 VDIfVfs.cpp \ 40 41 VDI.cpp \ 41 42 VMDK.cpp \ -
trunk/src/VBox/Storage/VDIfVfs.cpp
r47342 r47345 1 1 /* $Id$ */ 2 2 /** @file 3 * Virtual Disk Container implementation. - VFSglue.3 * Virtual Disk Image (VDI), I/O interface to IPRT VFS I/O stream glue. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2012 Oracle Corporation7 * Copyright (C) 2012-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 39 39 * The internal data of a DVM volume I/O stream. 40 40 */ 41 typedef struct VD VFSFILE42 { 43 /** The volume the VFS file belongs to. */44 PV BOXHDD pDisk;45 /** Current position. */46 uint64_t offCurPos;47 /** Flags given during creation. */48 uint 32_t fFlags;49 } VD VFSFILE;41 typedef struct VDIFVFSIOS 42 { 43 /** The VD I/O interface we wrap. */ 44 PVDINTERFACEIO pVDIfsIo; 45 /** User pointer to pass to the VD I/O interface methods. */ 46 void *pvStorage; 47 /** The current stream position relative to the VDIfCreateVfsStream call. */ 48 uint64_t offCurPos; 49 } VDIFVFSIOS; 50 50 /** Pointer to a the internal data of a DVM volume file. */ 51 typedef VDVFSFILE *PVDVFSFILE; 52 53 /** 54 * VD read helper taking care of unaligned accesses. 55 * 56 * @return VBox status code. 57 * @param pDisk VD disk container. 58 * @param off Offset to start reading from. 59 * @param pvBuf Pointer to the buffer to read into. 60 * @param cbRead Amount of bytes to read. 61 */ 62 static int vdReadHelper(PVBOXHDD pDisk, uint64_t off, void *pvBuf, size_t cbRead) 63 { 64 int rc = VINF_SUCCESS; 65 66 /* Take shortcut if possible. */ 67 if ( off % 512 == 0 68 && cbRead % 512 == 0) 69 rc = VDRead(pDisk, off, pvBuf, cbRead); 70 else 71 { 72 uint8_t *pbBuf = (uint8_t *)pvBuf; 73 uint8_t abBuf[512]; 74 75 /* Unaligned access, make it aligned. */ 76 if (off % 512 != 0) 77 { 78 uint64_t offAligned = off & ~(uint64_t)(512 - 1); 79 size_t cbToCopy = 512 - (off - offAligned); 80 rc = VDRead(pDisk, offAligned, abBuf, 512); 81 if (RT_SUCCESS(rc)) 82 { 83 memcpy(pbBuf, &abBuf[off - offAligned], cbToCopy); 84 pbBuf += cbToCopy; 85 off += cbToCopy; 86 cbRead -= cbToCopy; 87 } 88 } 89 90 if ( RT_SUCCESS(rc) 91 && (cbRead & ~(uint64_t)(512 - 1))) 92 { 93 size_t cbReadAligned = cbRead & ~(uint64_t)(512 - 1); 94 95 Assert(!(off % 512)); 96 rc = VDRead(pDisk, off, pbBuf, cbReadAligned); 97 if (RT_SUCCESS(rc)) 98 { 99 pbBuf += cbReadAligned; 100 off += cbReadAligned; 101 cbRead -= cbReadAligned; 102 } 103 } 104 105 if ( RT_SUCCESS(rc) 106 && cbRead) 107 { 108 Assert(cbRead < 512); 109 Assert(!(off % 512)); 110 111 rc = VDRead(pDisk, off, abBuf, 512); 112 if (RT_SUCCESS(rc)) 113 memcpy(pbBuf, abBuf, cbRead); 114 } 115 } 116 117 return rc; 118 } 119 120 121 /** 122 * VD write helper taking care of unaligned accesses. 123 * 124 * @return VBox status code. 125 * @param pDisk VD disk container. 126 * @param off Offset to start writing to. 127 * @param pvBuf Pointer to the buffer to read from. 128 * @param cbWrite Amount of bytes to write. 129 */ 130 static int vdWriteHelper(PVBOXHDD pDisk, uint64_t off, const void *pvBuf, size_t cbWrite) 131 { 132 int rc = VINF_SUCCESS; 133 134 /* Take shortcut if possible. */ 135 if ( off % 512 == 0 136 && cbWrite % 512 == 0) 137 rc = VDWrite(pDisk, off, pvBuf, cbWrite); 138 else 139 { 140 uint8_t *pbBuf = (uint8_t *)pvBuf; 141 uint8_t abBuf[512]; 142 143 /* Unaligned access, make it aligned. */ 144 if (off % 512 != 0) 145 { 146 uint64_t offAligned = off & ~(uint64_t)(512 - 1); 147 size_t cbToCopy = 512 - (off - offAligned); 148 rc = VDRead(pDisk, offAligned, abBuf, 512); 149 if (RT_SUCCESS(rc)) 150 { 151 memcpy(&abBuf[off - offAligned], pbBuf, cbToCopy); 152 rc = VDWrite(pDisk, offAligned, abBuf, 512); 153 154 pbBuf += cbToCopy; 155 off += cbToCopy; 156 cbWrite -= cbToCopy; 157 } 158 } 159 160 if ( RT_SUCCESS(rc) 161 && (cbWrite & ~(uint64_t)(512 - 1))) 162 { 163 size_t cbWriteAligned = cbWrite & ~(uint64_t)(512 - 1); 164 165 Assert(!(off % 512)); 166 rc = VDWrite(pDisk, off, pbBuf, cbWriteAligned); 167 if (RT_SUCCESS(rc)) 168 { 169 pbBuf += cbWriteAligned; 170 off += cbWriteAligned; 171 cbWrite -= cbWriteAligned; 172 } 173 } 174 175 if ( RT_SUCCESS(rc) 176 && cbWrite) 177 { 178 Assert(cbWrite < 512); 179 Assert(!(off % 512)); 180 181 rc = VDRead(pDisk, off, abBuf, 512); 182 if (RT_SUCCESS(rc)) 183 { 184 memcpy(abBuf, pbBuf, cbWrite); 185 rc = VDWrite(pDisk, off, abBuf, 512); 186 } 187 } 188 } 189 190 return rc; 191 } 51 typedef VDIFVFSIOS *PVDIFVFSIOS; 52 192 53 193 54 … … 195 56 * @interface_method_impl{RTVFSOBJOPS,pfnClose} 196 57 */ 197 static DECLCALLBACK(int) vdVfsFile_Close(void *pvThis) 198 { 199 PVDVFSFILE pThis = (PVDVFSFILE)pvThis; 200 201 if (pThis->fFlags & VD_VFSFILE_DESTROY_ON_RELEASE) 202 VDDestroy(pThis->pDisk); 203 58 static DECLCALLBACK(int) vdIfVfsIos_Close(void *pvThis) 59 { 60 /* We don't close anything. */ 204 61 return VINF_SUCCESS; 205 62 } … … 209 66 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo} 210 67 */ 211 static DECLCALLBACK(int) vdVfsFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, 212 RTFSOBJATTRADD enmAddAttr) 68 static DECLCALLBACK(int) vdIfVfsIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 213 69 { 214 70 NOREF(pvThis); … … 222 78 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead} 223 79 */ 224 static DECLCALLBACK(int) vdVfsFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead) 225 { 226 PVDVFSFILE pThis = (PVDVFSFILE)pvThis; 227 int rc = VINF_SUCCESS; 228 229 Assert(pSgBuf->cSegs == 1); 230 NOREF(fBlocking); 80 static DECLCALLBACK(int) vdIfVfsIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead) 81 { 82 PVDIFVFSIOS pThis = (PVDIFVFSIOS)pvThis; 83 Assert(pSgBuf->cSegs == 1); NOREF(fBlocking); 231 84 232 85 /* 233 * Find the current position and check if it's within the volume.86 * This may end up being a little more complicated, esp. wrt VERR_EOF. 234 87 */ 235 uint64_t offUnsigned = off < 0 ? pThis->offCurPos : (uint64_t)off; 236 if (offUnsigned >= VDGetSize(pThis->pDisk, VD_LAST_IMAGE)) 237 { 238 if (pcbRead) 239 { 240 *pcbRead = 0; 241 pThis->offCurPos = offUnsigned; 242 return VINF_EOF; 243 } 244 return VERR_EOF; 245 } 246 247 size_t cbLeftToRead; 248 if (offUnsigned + pSgBuf->paSegs[0].cbSeg > VDGetSize(pThis->pDisk, VD_LAST_IMAGE)) 249 { 250 if (!pcbRead) 251 return VERR_EOF; 252 *pcbRead = cbLeftToRead = (size_t)(VDGetSize(pThis->pDisk, VD_LAST_IMAGE) - offUnsigned); 253 } 254 else 255 { 256 cbLeftToRead = pSgBuf->paSegs[0].cbSeg; 257 if (pcbRead) 258 *pcbRead = cbLeftToRead; 259 } 88 int rc = vdIfIoFileReadSync(pThis->pVDIfsIo, pThis->pvStorage, off, pSgBuf[0].pvSegCur, pSgBuf->paSegs[0].cbSeg, pcbRead); 89 if (RT_SUCCESS(rc)) 90 pThis->offCurPos = off + (pcbRead ? *pcbRead : pSgBuf->paSegs[0].cbSeg); 91 return rc; 92 } 93 94 95 /** 96 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite} 97 */ 98 static DECLCALLBACK(int) vdIfVfsIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten) 99 { 100 PVDIFVFSIOS pThis = (PVDIFVFSIOS)pvThis; 101 Assert(pSgBuf->cSegs == 1); NOREF(fBlocking); 260 102 261 103 /* 262 * Ok, we've got a valid stretch within the file. Do the reading.104 * This may end up being a little more complicated, esp. wrt VERR_EOF. 263 105 */ 264 if (cbLeftToRead > 0) 265 { 266 rc = vdReadHelper(pThis->pDisk, (uint64_t)off, pSgBuf->paSegs[0].pvSeg, cbLeftToRead); 267 if (RT_SUCCESS(rc)) 268 offUnsigned += cbLeftToRead; 269 } 270 271 pThis->offCurPos = offUnsigned; 272 return rc; 273 } 274 275 276 /** 277 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite} 278 */ 279 static DECLCALLBACK(int) vdVfsFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten) 280 { 281 PVDVFSFILE pThis = (PVDVFSFILE)pvThis; 282 int rc = VINF_SUCCESS; 283 284 Assert(pSgBuf->cSegs == 1); 285 NOREF(fBlocking); 286 287 /* 288 * Find the current position and check if it's within the volume. 289 * Writing beyond the end of a volume is not supported. 290 */ 291 uint64_t offUnsigned = off < 0 ? pThis->offCurPos : (uint64_t)off; 292 if (offUnsigned >= VDGetSize(pThis->pDisk, VD_LAST_IMAGE)) 293 { 294 if (pcbWritten) 295 { 296 *pcbWritten = 0; 297 pThis->offCurPos = offUnsigned; 298 } 299 return VERR_NOT_SUPPORTED; 300 } 301 302 size_t cbLeftToWrite; 303 if (offUnsigned + pSgBuf->paSegs[0].cbSeg > VDGetSize(pThis->pDisk, VD_LAST_IMAGE)) 304 { 305 if (!pcbWritten) 306 return VERR_EOF; 307 *pcbWritten = cbLeftToWrite = (size_t)(VDGetSize(pThis->pDisk, VD_LAST_IMAGE) - offUnsigned); 308 } 309 else 310 { 311 cbLeftToWrite = pSgBuf->paSegs[0].cbSeg; 312 if (pcbWritten) 313 *pcbWritten = cbLeftToWrite; 314 } 315 316 /* 317 * Ok, we've got a valid stretch within the file. Do the reading. 318 */ 319 if (cbLeftToWrite > 0) 320 { 321 rc = vdWriteHelper(pThis->pDisk, (uint64_t)off, pSgBuf->paSegs[0].pvSeg, cbLeftToWrite); 322 if (RT_SUCCESS(rc)) 323 offUnsigned += cbLeftToWrite; 324 } 325 326 pThis->offCurPos = offUnsigned; 106 int rc = vdIfIoFileWriteSync(pThis->pVDIfsIo, pThis->pvStorage, off, pSgBuf[0].pvSegCur, pSgBuf->paSegs[0].cbSeg, pcbWritten); 107 if (RT_SUCCESS(rc)) 108 pThis->offCurPos = off + (pcbWritten ? *pcbWritten : pSgBuf->paSegs[0].cbSeg); 327 109 return rc; 328 110 } … … 332 114 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush} 333 115 */ 334 static DECLCALLBACK(int) vd VfsFile_Flush(void *pvThis)335 { 336 PVD VFSFILE pThis = (PVDVFSFILE)pvThis;337 return VDFlush(pThis->pDisk);116 static DECLCALLBACK(int) vdIfVfsIos_Flush(void *pvThis) 117 { 118 PVDIFVFSIOS pThis = (PVDIFVFSIOS)pvThis; 119 return vdIfIoFileFlushSync(pThis->pVDIfsIo, pThis->pvStorage); 338 120 } 339 121 … … 342 124 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne} 343 125 */ 344 static DECLCALLBACK(int) vd VfsFile_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,126 static DECLCALLBACK(int) vdIfVfsIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, 345 127 uint32_t *pfRetEvents) 346 128 { … … 361 143 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell} 362 144 */ 363 static DECLCALLBACK(int) vd VfsFile_Tell(void *pvThis, PRTFOFF poffActual)364 { 365 PVD VFSFILE pThis = (PVDVFSFILE)pvThis;145 static DECLCALLBACK(int) vdIfVfsIos_Tell(void *pvThis, PRTFOFF poffActual) 146 { 147 PVDIFVFSIOS pThis = (PVDIFVFSIOS)pvThis; 366 148 *poffActual = pThis->offCurPos; 367 149 return VINF_SUCCESS; … … 369 151 370 152 371 /**372 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}373 */374 static DECLCALLBACK(int) vdVfsFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)375 {376 NOREF(pvThis);377 NOREF(fMode);378 NOREF(fMask);379 return VERR_NOT_SUPPORTED;380 }381 382 383 /**384 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}385 */386 static DECLCALLBACK(int) vdVfsFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,387 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)388 {389 NOREF(pvThis);390 NOREF(pAccessTime);391 NOREF(pModificationTime);392 NOREF(pChangeTime);393 NOREF(pBirthTime);394 return VERR_NOT_SUPPORTED;395 }396 397 398 /**399 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}400 */401 static DECLCALLBACK(int) vdVfsFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)402 {403 NOREF(pvThis);404 NOREF(uid);405 NOREF(gid);406 return VERR_NOT_SUPPORTED;407 }408 409 410 /**411 * @interface_method_impl{RTVFSFILEOPS,pfnSeek}412 */413 static DECLCALLBACK(int) vdVfsFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)414 {415 PVDVFSFILE pThis = (PVDVFSFILE)pvThis;416 417 /*418 * Seek relative to which position.419 */420 uint64_t offWrt;421 switch (uMethod)422 {423 case RTFILE_SEEK_BEGIN:424 offWrt = 0;425 break;426 427 case RTFILE_SEEK_CURRENT:428 offWrt = pThis->offCurPos;429 break;430 431 case RTFILE_SEEK_END:432 offWrt = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);433 break;434 435 default:436 return VERR_INTERNAL_ERROR_5;437 }438 439 /*440 * Calc new position, take care to stay within bounds.441 *442 * @todo: Setting position beyond the end of the disk does not make sense.443 */444 uint64_t offNew;445 if (offSeek == 0)446 offNew = offWrt;447 else if (offSeek > 0)448 {449 offNew = offWrt + offSeek;450 if ( offNew < offWrt451 || offNew > RTFOFF_MAX)452 offNew = RTFOFF_MAX;453 }454 else if ((uint64_t)-offSeek < offWrt)455 offNew = offWrt + offSeek;456 else457 offNew = 0;458 459 /*460 * Update the state and set return value.461 */462 pThis->offCurPos = offNew;463 464 *poffActual = offNew;465 return VINF_SUCCESS;466 }467 468 469 /**470 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}471 */472 static DECLCALLBACK(int) vdVfsFile_QuerySize(void *pvThis, uint64_t *pcbFile)473 {474 PVDVFSFILE pThis = (PVDVFSFILE)pvThis;475 *pcbFile = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);476 return VINF_SUCCESS;477 }478 153 479 154 … … 481 156 * Standard file operations. 482 157 */ 483 DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_vdVfsStdFileOps = 484 { 485 { /* Stream */ 486 { /* Obj */ 487 RTVFSOBJOPS_VERSION, 488 RTVFSOBJTYPE_FILE, 489 "VDFile", 490 vdVfsFile_Close, 491 vdVfsFile_QueryInfo, 492 RTVFSOBJOPS_VERSION 493 }, 494 RTVFSIOSTREAMOPS_VERSION, 495 RTVFSIOSTREAMOPS_FEAT_NO_SG, 496 vdVfsFile_Read, 497 vdVfsFile_Write, 498 vdVfsFile_Flush, 499 vdVfsFile_PollOne, 500 vdVfsFile_Tell, 501 NULL /*Skip*/, 502 NULL /*ZeroFill*/, 503 RTVFSIOSTREAMOPS_VERSION, 158 DECL_HIDDEN_CONST(const RTVFSIOSTREAMOPS) g_vdIfVfsStdIosOps = 159 { 160 { /* Obj */ 161 RTVFSOBJOPS_VERSION, 162 RTVFSOBJTYPE_FILE, 163 "VDIfIos", 164 vdIfVfsIos_Close, 165 vdIfVfsIos_QueryInfo, 166 RTVFSOBJOPS_VERSION 504 167 }, 505 RTVFSFILEOPS_VERSION, 506 /*RTVFSIOFILEOPS_FEAT_NO_AT_OFFSET*/ 0, 507 { /* ObjSet */ 508 RTVFSOBJSETOPS_VERSION, 509 RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet), 510 vdVfsFile_SetMode, 511 vdVfsFile_SetTimes, 512 vdVfsFile_SetOwner, 513 RTVFSOBJSETOPS_VERSION 514 }, 515 vdVfsFile_Seek, 516 vdVfsFile_QuerySize, 517 RTVFSFILEOPS_VERSION 168 RTVFSIOSTREAMOPS_VERSION, 169 RTVFSIOSTREAMOPS_FEAT_NO_SG, 170 vdIfVfsIos_Read, 171 vdIfVfsIos_Write, 172 vdIfVfsIos_Flush, 173 vdIfVfsIos_PollOne, 174 vdIfVfsIos_Tell, 175 NULL /*Skip*/, 176 NULL /*ZeroFill*/, 177 RTVFSIOSTREAMOPS_VERSION, 518 178 }; 519 179 520 180 521 VBOXDDU_DECL(int) VDCreateVfsFileFromDisk(PVBOXHDD pDisk, uint32_t fFlags, 522 PRTVFSFILE phVfsFile) 523 { 524 AssertPtrReturn(pDisk, VERR_INVALID_HANDLE); 525 AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER); 526 AssertReturn((fFlags & ~VD_VFSFILE_FLAGS_MASK) == 0, VERR_INVALID_PARAMETER); 181 VBOXDDU_DECL(int) VDIfCreateVfsStream(PVDINTERFACEIO pVDIfsIo, void *pvStorage, uint32_t fFlags, PRTVFSIOSTREAM phVfsIos) 182 { 183 AssertPtrReturn(pVDIfsIo, VERR_INVALID_HANDLE); 184 AssertPtrReturn(phVfsIos, VERR_INVALID_POINTER); 527 185 528 186 /* 529 187 * Create the volume file. 530 188 */ 531 RTVFS FILE hVfsFile;532 PVD VFSFILEpThis;533 int rc = RTVfsNew File(&g_vdVfsStdFileOps, sizeof(*pThis), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_WRITE,534 NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pThis);189 RTVFSIOSTREAM hVfsIos; 190 PVDIFVFSIOS pThis; 191 int rc = RTVfsNewIoStream(&g_vdIfVfsStdIosOps, sizeof(*pThis), fFlags, 192 NIL_RTVFS, NIL_RTVFSLOCK, &hVfsIos, (void **)&pThis); 535 193 if (RT_SUCCESS(rc)) 536 194 { 195 pThis->pVDIfsIo = pVDIfsIo; 196 pThis->pvStorage = pvStorage; 537 197 pThis->offCurPos = 0; 538 pThis->pDisk = pDisk; 539 pThis->fFlags = fFlags; 540 541 *phVfsFile = hVfsFile; 198 199 *phVfsIos = hVfsIos; 542 200 return VINF_SUCCESS; 543 201 }
Note:
See TracChangeset
for help on using the changeset viewer.