Beispiel #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;
}
/**
 * Add an entry for an I/O stream using a passthru stream.
 *
 * The passthru I/O stream will hash all the data read from or written to the
 * stream and automatically add an entry to the manifest with the desired
 * attributes when it is released.  Alternatively one can call
 * RTManifestPtIosAddEntryNow() to have more control over exactly when this
 * action is performed and which status it yields.
 *
 * @returns IPRT status code.
 * @param   hManifest           The manifest to add the entry to.
 * @param   hVfsIos             The I/O stream to pass thru to/from.
 * @param   pszEntry            The entry name.
 * @param   fAttrs              The attributes to create for this stream.
 * @param   fReadOrWrite        Whether it's a read or write I/O stream.
 * @param   phVfsIosPassthru    Where to return the new handle.
 */
RTDECL(int) RTManifestEntryAddPassthruIoStream(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, const char *pszEntry,
                                               uint32_t fAttrs, bool fReadOrWrite, PRTVFSIOSTREAM phVfsIosPassthru)
{
    /*
     * Validate input.
     */
    AssertReturn(fAttrs < RTMANIFEST_ATTR_END, VERR_INVALID_PARAMETER);
    AssertPtr(pszEntry);
    AssertPtr(phVfsIosPassthru);
    uint32_t cRefs = RTManifestRetain(hManifest);
    AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
    cRefs = RTVfsIoStrmRetain(hVfsIos);
    AssertReturnStmt(cRefs != UINT32_MAX, RTManifestRelease(hManifest), VERR_INVALID_HANDLE);

    /*
     * Create an instace of the passthru I/O stream.
     */
    PRTMANIFESTPTIOS pThis;
    RTVFSIOSTREAM    hVfsPtIos;
    int rc = RTVfsNewIoStream(&g_rtManifestPassthruIosOps, sizeof(*pThis), fReadOrWrite ? RTFILE_O_READ : RTFILE_O_WRITE,
                              NIL_RTVFS, NIL_RTVFSLOCK, &hVfsPtIos, (void **)&pThis);
    if (RT_SUCCESS(rc))
    {
        pThis->hVfsIos          = hVfsIos;
        pThis->pHashes          = rtManifestHashesCreate(fAttrs);
        pThis->hManifest        = hManifest;
        pThis->fReadOrWrite     = fReadOrWrite;
        pThis->fAddedEntry      = false;
        pThis->pszEntry         = RTStrDup(pszEntry);
        if (pThis->pszEntry && pThis->pHashes)
        {
            *phVfsIosPassthru = hVfsPtIos;
            return VINF_SUCCESS;
        }

        RTVfsIoStrmRelease(hVfsPtIos);
    }
    else
    {
        RTVfsIoStrmRelease(hVfsIos);
        RTManifestRelease(hManifest);
    }
    return rc;
}