/** * 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; }