VirtualBox

Ignore:
Timestamp:
Jul 23, 2013 12:27:35 PM (11 years ago)
Author:
vboxsync
Message:

pr6022. OVA appliance don't fail when a certificate file exists. GZIP support has been implemented (first version).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/ApplianceImplIO.cpp

    r46971 r47340  
    2424#include "ApplianceImpl.h"
    2525#include "ApplianceImplPrivate.h"
    26 
     26#include "VirtualBoxImpl.h"
     27
     28#include <iprt/zip.h>
    2729#include <iprt/tar.h>
    2830#include <iprt/sha.h>
     
    3234#include <iprt/circbuf.h>
    3335#include <VBox/vd.h>
     36#include <zlib.h>
    3437
    3538/******************************************************************************
     
    9295} SHASTORAGEINTERNAL, *PSHASTORAGEINTERNAL;
    9396
     97typedef 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
    94129/******************************************************************************
    95130 *   Defined Constants And Macros                                             *
     
    110145#endif
    111146
     147/** Buffer for the decompressed data. */
     148//static uint8_t *compressedBuffer;
     149/** The current size of the compressed data*/
     150static size_t   cbComprData;
     151/** The current offset into the compressed data */
     152static size_t   offComprData;
     153
    112154/******************************************************************************
    113155 *   Internal Functions                                                       *
    114156 ******************************************************************************/
     157//static DECLCALLBACK(int) CopyCompressedDataToBuffer(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbRead);
    115158
    116159/******************************************************************************
     
    11741217
    11751218/******************************************************************************
     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/******************************************************************************
    11761637 *   Public Functions                                                         *
    11771638 ******************************************************************************/
     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//}
    11781659
    11791660PVDINTERFACEIO ShaCreateInterface()
     
    13391820}
    13401821
     1822int 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.

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