Exemplo n.º 1
0
/**
 * Adds an entry for a file with the specified set of attributes.
 *
 * @returns IPRT status code.
 *
 * @param   hManifest           The manifest handle.
 * @param   hVfsIos             The I/O stream handle of the entry.  This will
 *                              be processed to its end on successful return.
 *                              (Must be positioned at the start to get
 *                              the expected results.)
 * @param   pszEntry            The entry name.
 * @param   fAttrs              The attributes to create for this stream.
 */
RTDECL(int) RTManifestEntryAddIoStream(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, const char *pszEntry, uint32_t fAttrs)
{
    /*
     * Note! This is a convenicence function, so just use the available public
     *       methods to get the job done.
     */
    AssertReturn(fAttrs < RTMANIFEST_ATTR_END, VERR_INVALID_PARAMETER);
    AssertPtr(pszEntry);

    /*
     * Allocate and initialize the hash contexts, hash digests and I/O buffer.
     */
    PRTMANIFESTHASHES pHashes = rtManifestHashesCreate(fAttrs);
    if (!pHashes)
        return VERR_NO_TMP_MEMORY;

    int         rc;
    size_t      cbBuf = _1M;
    void       *pvBuf = RTMemTmpAlloc(cbBuf);
    if (RT_UNLIKELY(!pvBuf))
    {
        cbBuf = _4K;
        pvBuf = RTMemTmpAlloc(cbBuf);
    }
    if (RT_LIKELY(pvBuf))
    {
        /*
         * Process the stream data.
         */
        for (;;)
        {
            size_t cbRead;
            rc = RTVfsIoStrmRead(hVfsIos, pvBuf, cbBuf, true /*fBlocking*/, &cbRead);
            if (   (rc == VINF_EOF && cbRead == 0)
                || RT_FAILURE(rc))
                break;
            rtManifestHashesUpdate(pHashes, pvBuf, cbRead);
        }
        RTMemTmpFree(pvBuf);
        if (RT_SUCCESS(rc))
        {
            /*
             * Add the entry with the finalized hashes.
             */
            rtManifestHashesFinal(pHashes);
            rc = RTManifestEntryAdd(hManifest, pszEntry);
            if (RT_SUCCESS(rc))
                rc = rtManifestHashesSetAttrs(pHashes, hManifest, pszEntry);
        }
    }
    else
    {
        rtManifestHashesDestroy(pHashes);
        rc = VERR_NO_TMP_MEMORY;
    }
    return rc;
}
/**
 * Updates the hashes with a scather/gather buffer.
 *
 * @param   pThis               The passthru I/O stream instance data.
 * @param   pSgBuf              The scather/gather buffer.
 * @param   cbLeft              The number of bytes to take from the buffer.
 */
static void rtManifestPtIos_UpdateHashes(PRTMANIFESTPTIOS pThis, PCRTSGBUF pSgBuf, size_t cbLeft)
{
    for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
    {
        size_t cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
        if (cbSeg > cbLeft)
            cbSeg = cbLeft;
        rtManifestHashesUpdate(pThis->pHashes, pSgBuf->paSegs[iSeg].pvSeg, cbSeg);
        cbLeft -= cbSeg;
        if (!cbLeft)
            break;
    }
}