Changeset 47340 in vbox for trunk/src/VBox/Main/src-server/ApplianceImplIO.cpp
- Timestamp:
- Jul 23, 2013 12:27:35 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/ApplianceImplIO.cpp
r46971 r47340 24 24 #include "ApplianceImpl.h" 25 25 #include "ApplianceImplPrivate.h" 26 26 #include "VirtualBoxImpl.h" 27 28 #include <iprt/zip.h> 27 29 #include <iprt/tar.h> 28 30 #include <iprt/sha.h> … … 32 34 #include <iprt/circbuf.h> 33 35 #include <VBox/vd.h> 36 #include <zlib.h> 34 37 35 38 /****************************************************************************** … … 92 95 } SHASTORAGEINTERNAL, *PSHASTORAGEINTERNAL; 93 96 97 typedef struct GZIPSTORAGEINTERNAL 98 { 99 /** Completion callback. */ 100 PFNVDCOMPLETED pfnCompleted; 101 /** Storage handle for the next callback in chain. */ 102 void *pvStorage; 103 /** Current file open mode. */ 104 uint32_t fOpenMode; 105 /** Circular buffer used for transferring data from/to the worker thread. */ 106 PRTCIRCBUF pCircBuf; 107 /** Current absolute position (regardless of the real read/written data). */ 108 uint64_t cbCurAll; 109 /** Current real position in the file. */ 110 uint64_t cbCurFile; 111 /** Handle of the worker thread. */ 112 RTTHREAD pWorkerThread; 113 /** Status of the worker thread. */ 114 volatile uint32_t u32Status; 115 /** Event for signaling a new status. */ 116 RTSEMEVENT newStatusEvent; 117 /** Event for signaling a finished task of the worker thread. */ 118 RTSEMEVENT workFinishedEvent; 119 /** Write mode only: Memory buffer for writing zeros. */ 120 void *pvZeroBuf; 121 /** Write mode only: Size of the zero memory buffer. */ 122 size_t cbZeroBuf; 123 /** Read mode only: Indicate if we reached end of file. */ 124 volatile bool fEOF; 125 // uint64_t calls; 126 // uint64_t waits; 127 } GZIPSTORAGEINTERNAL, *PGZIPSTORAGEINTERNAL; 128 94 129 /****************************************************************************** 95 130 * Defined Constants And Macros * … … 110 145 #endif 111 146 147 /** Buffer for the decompressed data. */ 148 //static uint8_t *compressedBuffer; 149 /** The current size of the compressed data*/ 150 static size_t cbComprData; 151 /** The current offset into the compressed data */ 152 static size_t offComprData; 153 112 154 /****************************************************************************** 113 155 * Internal Functions * 114 156 ******************************************************************************/ 157 //static DECLCALLBACK(int) CopyCompressedDataToBuffer(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbRead); 115 158 116 159 /****************************************************************************** … … 1174 1217 1175 1218 /****************************************************************************** 1219 * Internal: RTGZIP interface 1220 ******************************************************************************/ 1221 1222 //DECLCALLBACK(int) gzipCalcWorkerThread(RTTHREAD /* aThread */, void *pvUser) 1223 //{ 1224 // /* Validate input. */ 1225 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1226 // 1227 // PGZIPSTORAGEINTERNAL pInt = (PGZIPSTORAGEINTERNAL)pvUser; 1228 // 1229 // PVDINTERFACEIO pIfIo = VDIfIoGet(pInt->pShaStorage->pVDImageIfaces); 1230 // AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1231 // 1232 // int rc = VINF_SUCCESS; 1233 // bool fLoop = true; 1234 // while (fLoop) 1235 // { 1236 // /* What should we do next? */ 1237 // uint32_t u32Status = ASMAtomicReadU32(&pInt->u32Status); 1238 //// RTPrintf("status: %d\n", u32Status); 1239 // switch (u32Status) 1240 // { 1241 // case STATUS_WAIT: 1242 // { 1243 // /* Wait for new work. */ 1244 // rc = RTSemEventWait(pInt->newStatusEvent, 100); 1245 // if ( RT_FAILURE(rc) 1246 // && rc != VERR_TIMEOUT) 1247 // fLoop = false; 1248 // break; 1249 // } 1250 // case STATUS_READ: 1251 // { 1252 // ASMAtomicCmpXchgU32(&pInt->u32Status, STATUS_READING, STATUS_READ); 1253 // size_t cbAvail = RTCircBufFree(pInt->pCircBuf); 1254 // size_t cbMemAllWrite = 0; 1255 // /* First loop over all the available memory in the circular 1256 // * memory buffer (could be turn around at the end). */ 1257 // for (;;) 1258 // { 1259 // if ( cbMemAllWrite == cbAvail 1260 // || fLoop == false) 1261 // break; 1262 // char *pcBuf; 1263 // size_t cbMemToWrite = cbAvail - cbMemAllWrite; 1264 // size_t cbMemWrite = 0; 1265 // /* Try to acquire all the free space of the circular buffer. */ 1266 // RTCircBufAcquireWriteBlock(pInt->pCircBuf, cbMemToWrite, (void**)&pcBuf, &cbMemWrite); 1267 // /* Second, read as long as we filled all the memory. The 1268 // * read method could also split the reads up into to 1269 // * smaller parts. */ 1270 // size_t cbAllRead = 0; 1271 // for (;;) 1272 // { 1273 // if (cbAllRead == cbMemWrite) 1274 // break; 1275 // size_t cbToRead = cbMemWrite - cbAllRead; 1276 // size_t cbRead = 0; 1277 // rc = vdIfIoFileReadSync(pIfIo, pInt->pvStorage, pInt->cbCurFile, &pcBuf[cbAllRead], cbToRead, &cbRead); 1278 // if (RT_FAILURE(rc)) 1279 // { 1280 // fLoop = false; 1281 // break; 1282 // } 1283 // /* This indicates end of file. Stop reading. */ 1284 // if (cbRead == 0) 1285 // { 1286 // fLoop = false; 1287 // ASMAtomicWriteBool(&pInt->fEOF, true); 1288 // break; 1289 // } 1290 // cbAllRead += cbRead; 1291 // pInt->cbCurFile += cbRead; 1292 // } 1293 // /* Update the GZIP context with the next data block. */ 1294 // if (RT_SUCCESS(rc)) 1295 // { 1296 // RTSha256Update(&pInt->ctx.Sha256, pcBuf, cbAllRead); 1297 // } 1298 // /* Mark the block as full. */ 1299 // RTCircBufReleaseWriteBlock(pInt->pCircBuf, cbAllRead); 1300 // cbMemAllWrite += cbAllRead; 1301 // } 1302 // /* Reset the thread status and signal the main thread that we 1303 // * are finished. Use CmpXchg, so we not overwrite other states 1304 // * which could be signaled in the meantime. */ 1305 // if (ASMAtomicCmpXchgU32(&pInt->u32Status, STATUS_WAIT, STATUS_READING)) 1306 // rc = RTSemEventSignal(pInt->workFinishedEvent); 1307 // break; 1308 // } 1309 // case STATUS_END: 1310 // { 1311 // /* End signaled */ 1312 // fLoop = false; 1313 // break; 1314 // } 1315 // } 1316 // } 1317 // /* Cleanup any status changes to indicate we are finished. */ 1318 // ASMAtomicWriteU32(&pInt->u32Status, STATUS_END); 1319 // rc = RTSemEventSignal(pInt->workFinishedEvent); 1320 // return rc; 1321 //} 1322 // 1323 //DECLINLINE(int) gzipSignalManifestThread(PGZIPSTORAGEINTERNAL pInt, uint32_t uStatus) 1324 //{ 1325 // ASMAtomicWriteU32(&pInt->u32Status, uStatus); 1326 // return RTSemEventSignal(pInt->newStatusEvent); 1327 //} 1328 // 1329 //DECLINLINE(int) gzipWaitForManifestThreadFinished(PGZIPSTORAGEINTERNAL pInt) 1330 //{ 1331 //// RTPrintf("start\n"); 1332 // int rc = VINF_SUCCESS; 1333 // for (;;) 1334 // { 1335 //// RTPrintf(" wait\n"); 1336 // uint32_t u32Status = ASMAtomicReadU32(&pInt->u32Status); 1337 // if (!( u32Status == STATUS_WRITE 1338 // || u32Status == STATUS_WRITING 1339 // || u32Status == STATUS_READ 1340 // || u32Status == STATUS_READING)) 1341 // break; 1342 // rc = RTSemEventWait(pInt->workFinishedEvent, 100); 1343 // } 1344 // if (rc == VERR_TIMEOUT) 1345 // rc = VINF_SUCCESS; 1346 // return rc; 1347 //} 1348 // 1349 //DECLINLINE(int) gzipFlushCurBuf(PGZIPSTORAGEINTERNAL pInt) 1350 //{ 1351 // int rc = VINF_SUCCESS; 1352 // if (pInt->fOpenMode & RTFILE_O_WRITE) 1353 // { 1354 // /* Let the write worker thread start immediately. */ 1355 // rc = gzipSignalManifestThread(pInt, STATUS_WRITE); 1356 // if (RT_FAILURE(rc)) 1357 // return rc; 1358 // 1359 // /* Wait until the write worker thread has finished. */ 1360 // rc = gzipWaitForManifestThreadFinished(pInt); 1361 // } 1362 // 1363 // return rc; 1364 //} 1365 // 1366 //static int gzipOpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpen, 1367 // PFNVDCOMPLETED pfnCompleted, void **ppInt) 1368 //{ 1369 // /* Validate input. */ 1370 // AssertPtrReturn(pvUser, VERR_INVALID_PARAMETER); 1371 // AssertPtrReturn(pszLocation, VERR_INVALID_POINTER); 1372 // AssertPtrNullReturn(pfnCompleted, VERR_INVALID_PARAMETER); 1373 // AssertPtrReturn(ppInt, VERR_INVALID_POINTER); 1374 // AssertReturn((fOpen & RTFILE_O_READWRITE) != RTFILE_O_READWRITE, VERR_INVALID_PARAMETER); /* No read/write allowed */ 1375 // 1376 // DEBUG_PRINT_FLOW(); 1377 // 1378 // PGZIPSTORAGEINTERNAL pInt = (PGZIPSTORAGEINTERNAL)RTMemAllocZ(sizeof(GZIPSTORAGEINTERNAL)); 1379 // if (!pInt) 1380 // return VERR_NO_MEMORY; 1381 // 1382 // int rc = VINF_SUCCESS; 1383 // do 1384 // { 1385 // pInt->pfnCompleted = pfnCompleted; 1386 // pInt->fEOF = false; 1387 // pInt->fOpenMode = fOpen; 1388 // pInt->u32Status = STATUS_WAIT; 1389 // 1390 // /* Circular buffer in the read case. */ 1391 // rc = RTCircBufCreate(&pInt->pCircBuf, _1M * 2); 1392 // if (RT_FAILURE(rc)) 1393 // break; 1394 // 1395 // /* Create an event semaphore to indicate a state change for the worker 1396 // * thread. */ 1397 // rc = RTSemEventCreate(&pInt->newStatusEvent); 1398 // if (RT_FAILURE(rc)) 1399 // break; 1400 // /* Create an event semaphore to indicate a finished calculation of the 1401 // worker thread. */ 1402 // rc = RTSemEventCreate(&pInt->workFinishedEvent); 1403 // if (RT_FAILURE(rc)) 1404 // break; 1405 // /* Create the worker thread. */ 1406 // rc = RTThreadCreate(&pInt->pWorkerThread, gziCalcWorkerThread, pInt, 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 1407 // RTTHREADFLAGS_WAITABLE, "GZIP-Worker"); 1408 // if (RT_FAILURE(rc)) 1409 // break; 1410 // 1411 // /* Open the file. */ 1412 // rc = vdIfIoFileOpen(pIfIo, pszLocation, fOpen, pInt->pfnCompleted, 1413 // &pInt->pvStorage); 1414 // if (RT_FAILURE(rc)) 1415 // break; 1416 // 1417 // if (fOpen & RTFILE_O_READ) 1418 // { 1419 // /* Immediately let the worker thread start the reading. */ 1420 // rc = gzipSignalManifestThread(pInt, STATUS_READ); 1421 // } 1422 // } 1423 // while (0); 1424 // 1425 // if (RT_FAILURE(rc)) 1426 // { 1427 // if (pInt->pWorkerThread) 1428 // { 1429 // gzipSignalManifestThread(pInt, STATUS_END); 1430 // RTThreadWait(pInt->pWorkerThread, RT_INDEFINITE_WAIT, 0); 1431 // } 1432 // if (pInt->workFinishedEvent) 1433 // RTSemEventDestroy(pInt->workFinishedEvent); 1434 // if (pInt->newStatusEvent) 1435 // RTSemEventDestroy(pInt->newStatusEvent); 1436 // if (pInt->pCircBuf) 1437 // RTCircBufDestroy(pInt->pCircBuf); 1438 // if (pInt->pvZeroBuf) 1439 // RTMemFree(pInt->pvZeroBuf); 1440 // RTMemFree(pInt); 1441 // } 1442 // else 1443 // *ppInt = pInt; 1444 // 1445 // return rc; 1446 //} 1447 // 1448 //static int gzipCloseCallback(void *pvUser, void *pvStorage) 1449 //{ 1450 // /* Validate input. */ 1451 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1452 // AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); 1453 // 1454 // PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser; 1455 // PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces); 1456 // AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1457 // 1458 // PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvStorage; 1459 // 1460 // DEBUG_PRINT_FLOW(); 1461 // 1462 // int rc = VINF_SUCCESS; 1463 // 1464 // /* Make sure all pending writes are flushed */ 1465 // rc = gzipFlushCurBuf(pInt); 1466 // 1467 // if (pInt->pWorkerThread) 1468 // { 1469 // /* Signal the worker thread to end himself */ 1470 // rc = gzipSignalManifestThread(pInt, STATUS_END); 1471 // /* Worker thread stopped? */ 1472 // rc = RTThreadWait(pInt->pWorkerThread, RT_INDEFINITE_WAIT, 0); 1473 // } 1474 // 1475 // /* Close the file */ 1476 // rc = vdIfIoFileClose(pIfIo, pInt->pvStorage); 1477 // 1478 // /* Cleanup */ 1479 // if (pInt->workFinishedEvent) 1480 // RTSemEventDestroy(pInt->workFinishedEvent); 1481 // if (pInt->newStatusEvent) 1482 // RTSemEventDestroy(pInt->newStatusEvent); 1483 // if (pInt->pCircBuf) 1484 // RTCircBufDestroy(pInt->pCircBuf); 1485 // if (pInt->pvZeroBuf) 1486 // RTMemFree(pInt->pvZeroBuf); 1487 // RTMemFree(pInt); 1488 // 1489 // return rc; 1490 //} 1491 // 1492 //static int gzipDeleteCallback(void *pvUser, const char *pcszFilename) 1493 //{ 1494 // /* Validate input. */ 1495 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1496 // 1497 // DEBUG_PRINT_FLOW(); 1498 // 1499 // return VERR_NOT_IMPLEMENTED; 1500 //} 1501 // 1502 //static int gzipMoveCallback(void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove) 1503 //{ 1504 // /* Validate input. */ 1505 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1506 // 1507 // DEBUG_PRINT_FLOW(); 1508 // 1509 // return VERR_NOT_IMPLEMENTED; 1510 //} 1511 // 1512 //static int gzipGetFreeSpaceCallback(void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace) 1513 //{ 1514 // /* Validate input. */ 1515 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1516 // 1517 // DEBUG_PRINT_FLOW(); 1518 // 1519 // return VERR_NOT_IMPLEMENTED; 1520 //} 1521 // 1522 //static int gzipGetModificationTimeCallback(void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime) 1523 //{ 1524 // /* Validate input. */ 1525 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1526 // 1527 // DEBUG_PRINT_FLOW(); 1528 // 1529 // return VERR_NOT_IMPLEMENTED; 1530 //} 1531 // 1532 // 1533 //static int gzipGetSizeCallback(void *pvUser, void *pvStorage, uint64_t *pcbSize) 1534 //{ 1535 // /* Validate input. */ 1536 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1537 // AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); 1538 // 1539 // PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser; 1540 // PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces); 1541 // AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1542 // 1543 // PGZIPSTORAGEINTERNAL pInt = (PGZIPSTORAGEINTERNAL)pvStorage; 1544 // 1545 // DEBUG_PRINT_FLOW(); 1546 // 1547 // uint64_t cbSize; 1548 // int rc = vdIfIoFileGetSize(pIfIo, pInt->pvStorage, &cbSize); 1549 // if (RT_FAILURE(rc)) 1550 // return rc; 1551 // 1552 // *pcbSize = RT_MAX(pInt->cbCurAll, cbSize); 1553 // 1554 // return VINF_SUCCESS; 1555 //} 1556 // 1557 //static int gzipSetSizeCallback(void *pvUser, void *pvStorage, uint64_t cbSize) 1558 //{ 1559 // /* Validate input. */ 1560 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1561 // AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); 1562 // 1563 // PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser; 1564 // PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces); 1565 // AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1566 // 1567 // PGZIPSTORAGEINTERNAL pInt = (PGZIPSTORAGEINTERNAL)pvStorage; 1568 // 1569 // DEBUG_PRINT_FLOW(); 1570 // 1571 // return vdIfIoFileSetSize(pIfIo, pInt->pvStorage, cbSize); 1572 //} 1573 // 1574 //static int gzipWriteSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset, 1575 // const void *pvBuf, size_t cbWrite, size_t *pcbWritten) 1576 //{ 1577 // /* Validate input. */ 1578 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1579 // AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); 1580 // 1581 // PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser; 1582 // PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces); 1583 // AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1584 // 1585 // PGZIPSTORAGEINTERNAL pInt = (PGZIPSTORAGEINTERNAL)pvStorage; 1586 // 1587 // DEBUG_PRINT_FLOW(); 1588 // 1589 // int rc = VINF_SUCCESS; 1590 // 1591 // return VERR_NOT_IMPLEMENTED; 1592 //} 1593 // 1594 //static int gzipReadSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset, 1595 // void *pvBuf, size_t cbRead, size_t *pcbRead) 1596 //{ 1597 // /* Validate input. */ 1598 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1599 // AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); 1600 // 1601 // PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser; 1602 // PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces); 1603 // AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1604 // 1605 // DEBUG_PRINT_FLOW(); 1606 // 1607 // PGZIPSTORAGEINTERNAL pInt = (PGZIPSTORAGEINTERNAL)pvStorage; 1608 // 1609 // int rc = VINF_SUCCESS; 1610 // 1611 // return rc; 1612 //} 1613 // 1614 //static int gzipFlushSyncCallback(void *pvUser, void *pvStorage) 1615 //{ 1616 // /* Validate input. */ 1617 // AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 1618 // AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); 1619 // 1620 // PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser; 1621 // PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces); 1622 // AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1623 // 1624 // DEBUG_PRINT_FLOW(); 1625 // 1626 // PGZIPSTORAGEINTERNAL pInt = (PGZIPSTORAGEINTERNAL)pvStorage; 1627 // 1628 // /* Check if there is still something in the buffer. If yes, flush it. */ 1629 // int rc = gzipFlushCurBuf(pInt); 1630 // if (RT_FAILURE(rc)) 1631 // return rc; 1632 // 1633 // return vdIfIoFileFlushSync(pIfIo, pInt->pvStorage); 1634 //} 1635 1636 /****************************************************************************** 1176 1637 * Public Functions * 1177 1638 ******************************************************************************/ 1639 //PVDINTERFACEIO GzipCreateInterface() 1640 //{ 1641 // PVDINTERFACEIO pCallbacks = (PVDINTERFACEIO)RTMemAllocZ(sizeof(VDINTERFACEIO)); 1642 // if (!pCallbacks) 1643 // return NULL; 1644 // 1645 // pCallbacks->pfnOpen = gzipOpenCallback; 1646 // pCallbacks->pfnClose = gzipCloseCallback; 1647 // pCallbacks->pfnDelete = gzipDeleteCallback; 1648 // pCallbacks->pfnMove = gzipMoveCallback; 1649 // pCallbacks->pfnGetFreeSpace = gzipGetFreeSpaceCallback; 1650 // pCallbacks->pfnGetModificationTime = gzipGetModificationTimeCallback; 1651 // pCallbacks->pfnGetSize = gzipGetSizeCallback; 1652 // pCallbacks->pfnSetSize = gzipSetSizeCallback; 1653 // pCallbacks->pfnReadSync = gzipReadSyncCallback; 1654 // pCallbacks->pfnWriteSync = gzipWriteSyncCallback; 1655 // pCallbacks->pfnFlushSync = gzipFlushSyncCallback; 1656 // 1657 // return pCallbacks; 1658 //} 1178 1659 1179 1660 PVDINTERFACEIO ShaCreateInterface() … … 1339 1820 } 1340 1821 1822 int decompressImageAndSave(const char *pcszFullFilenameIn, const char *pcszFullFilenameOut, PVDINTERFACEIO pIfIo, void *pvUser) 1823 { 1824 /* Validate input. */ 1825 AssertPtrReturn(pIfIo, VERR_INVALID_POINTER); 1826 1827 void *pvStorage; 1828 int rc = pIfIo->pfnOpen(pvUser, pcszFullFilenameIn, 1829 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, 0, 1830 &pvStorage); 1831 if (RT_FAILURE(rc)) 1832 return rc; 1833 1834 Bytef *decompressedBuffer = 0; 1835 Bytef *compressedBuffer = 0; 1836 uint64_t cbTmpSize = _1M; 1837 size_t cbAllRead = 0; 1838 size_t cbAllWritten = 0; 1839 RTFILE pFile = NULL; 1840 z_stream gzipStream; 1841 1842 Utf8Str pathOut(pcszFullFilenameOut); 1843 pathOut = pathOut.stripFilename(); 1844 1845 Utf8Str fileIn(pcszFullFilenameIn); 1846 fileIn = fileIn.stripPath(); 1847 1848 do 1849 { 1850 if (RTFileExists(pcszFullFilenameOut) == false) 1851 { 1852 /* ensure the directory exists */ 1853 rc = VirtualBox::ensureFilePathExists(Utf8Str(pcszFullFilenameOut), true); 1854 if (FAILED(rc)) 1855 { 1856 rc = VBOX_E_FILE_ERROR; 1857 break; 1858 } 1859 1860 rc = RTFileOpen(&pFile, pcszFullFilenameOut, RTFILE_O_OPEN_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1861 } 1862 else 1863 { 1864 rc = RTFileOpen(&pFile, pcszFullFilenameOut, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1865 } 1866 1867 if (FAILED(rc) || pFile == NULL) 1868 { 1869 rc = VBOX_E_FILE_ERROR; 1870 break; 1871 } 1872 1873 compressedBuffer = (Bytef *)RTMemAlloc(cbTmpSize); 1874 1875 if (!compressedBuffer) 1876 { 1877 rc = VERR_NO_MEMORY; 1878 break; 1879 } 1880 1881 1882 decompressedBuffer = (Bytef *)RTMemAlloc(cbTmpSize*10); 1883 1884 if (!decompressedBuffer) 1885 { 1886 rc = VERR_NO_MEMORY; 1887 break; 1888 } 1889 1890 gzipStream.zalloc = Z_NULL; 1891 gzipStream.zfree = Z_NULL; 1892 gzipStream.opaque = Z_NULL; 1893 gzipStream.next_in = compressedBuffer; 1894 gzipStream.avail_in = 0; 1895 gzipStream.next_out = decompressedBuffer; 1896 gzipStream.avail_out = cbTmpSize*10; 1897 1898 rc = inflateInit2(&gzipStream, MAX_WBITS + 16 /* autodetect gzip header */); 1899 1900 if (rc < 0) 1901 { 1902 break; 1903 } 1904 1905 size_t cbRead = 0; 1906 size_t cbDecompressed = 0; 1907 bool fFinished = true; 1908 1909 for (;;) 1910 { 1911 if (fFinished == true) 1912 { 1913 rc = pIfIo->pfnReadSync(pvUser, pvStorage, cbAllRead, compressedBuffer, cbTmpSize, &cbRead); 1914 if ( RT_FAILURE(rc) 1915 || cbRead == 0) 1916 break; 1917 1918 gzipStream.avail_in = cbRead; 1919 gzipStream.avail_out = cbTmpSize*10; 1920 } 1921 1922 /* decompress the buffer */ 1923 rc = RTZipGzipDecompressBuffer(gzipStream, 1924 (uint32_t *)(&cbDecompressed), 1925 &fFinished); 1926 1927 if (RT_FAILURE(rc)) 1928 break; 1929 1930 rc = RTFileWrite(pFile, decompressedBuffer, cbDecompressed, &cbDecompressed); 1931 1932 if (RT_FAILURE(rc)) 1933 break; 1934 1935 cbAllWritten += cbDecompressed; 1936 cbAllRead += cbRead; 1937 } 1938 } while (0); 1939 1940 pIfIo->pfnClose(pvUser, pvStorage); 1941 1942 if (rc == VERR_EOF) 1943 rc = VINF_SUCCESS; 1944 1945 rc = inflateEnd(&gzipStream); 1946 1947 rc = RTFileClose(pFile); 1948 1949 if (decompressedBuffer) 1950 RTMemFree(decompressedBuffer); 1951 if (compressedBuffer) 1952 RTMemFree(compressedBuffer); 1953 1954 return rc; 1955 } 1956 1957
Note:
See TracChangeset
for help on using the changeset viewer.