/** * Basic API checks. */ static void tst1(void) { RTTestISub("Manifest creation"); size_t cbSize = 0; size_t iFailed = 0; /* * test1.txt = "This is a test text." * test2.txt = "Another test text." */ static RTMANIFESTTEST /*const*/ s_aFiles[] = /** @todo API misdesign, this should be const. */ { { "test1.txt", "794a8cc644b318ae6461aeea62915e399e441e8" }, { "test2.txt", "f17393902ee94c1e8bbd4bf417cdc70051feca00" } }; static const char s_szTestPattern[] = "SHA1 (test1.txt)= 794a8cc644b318ae6461aeea62915e399e441e8\n" "SHA1 (test2.txt)= f17393902ee94c1e8bbd4bf417cdc70051feca00\n" ; void *pvBuf = NULL; RTTESTI_CHECK_RC_RETV(RTManifestWriteFilesBuf(&pvBuf, &cbSize, RTDIGESTTYPE_SHA1, s_aFiles, 2), VINF_SUCCESS); /* Check returned memory size */ RTTESTI_CHECK_RETV(cbSize == strlen(s_szTestPattern)); /* Check for correct manifest file content */ RTTESTI_CHECK(memcmp(pvBuf, s_szTestPattern, cbSize) == 0); RTTestISub("Manifest verify"); RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 2, 0), VINF_SUCCESS); /* To little files to check */ RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 1, 0), VERR_MANIFEST_FILE_MISMATCH); /* Make the digest type invalid */ ((char*)pvBuf)[0] = 'L'; RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 2, 0), VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE); ((char*)pvBuf)[0] = 'S'; /* Restore */ /* Make the file name invalid */ ((char*)pvBuf)[8] = 'z'; RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 2, 0), VERR_MANIFEST_FILE_MISMATCH); ((char*)pvBuf)[8] = 's'; /* Restore */ /* Make the second digest invalid */ ((char*)pvBuf)[99] = '0'; RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 2, &iFailed), VERR_MANIFEST_DIGEST_MISMATCH); RTTESTI_CHECK(iFailed == 1); /* Cleanup */ RTMemFree(pvBuf); }
RTR3DECL(int) RTManifestWriteFiles(const char *pszManifestFile, RTDIGESTTYPE enmDigestType, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser) { /* Validate input */ AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER); AssertPtrReturn(papszFiles, VERR_INVALID_POINTER); AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_POINTER); RTFILE file; int rc = RTFileOpen(&file, pszManifestFile, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_ALL); if (RT_FAILURE(rc)) return rc; PRTMANIFESTTEST paFiles = 0; void *pvBuf = 0; do { paFiles = (PRTMANIFESTTEST)RTMemAllocZ(sizeof(RTMANIFESTTEST) * cFiles); if (!paFiles) { rc = VERR_NO_MEMORY; break; } RTMANIFESTCALLBACKDATA callback = { pfnProgressCallback, pvUser, cFiles, 0 }; for (size_t i = 0; i < cFiles; ++i) { paFiles[i].pszTestFile = papszFiles[i]; /* Calculate the SHA1 digest of every file */ if (pfnProgressCallback) { callback.cCurrentFile = i; rc = RTSha1DigestFromFile(paFiles[i].pszTestFile, (char**)&paFiles[i].pszTestDigest, rtSHAProgressCallback, &callback); } else rc = RTSha1DigestFromFile(paFiles[i].pszTestFile, (char**)&paFiles[i].pszTestDigest, NULL, NULL); if (RT_FAILURE(rc)) break; } if (RT_SUCCESS(rc)) { size_t cbSize = 0; rc = RTManifestWriteFilesBuf(&pvBuf, &cbSize, enmDigestType, paFiles, cFiles); if (RT_FAILURE(rc)) break; rc = RTFileWrite(file, pvBuf, cbSize, 0); } }while (0); RTFileClose(file); /* Cleanup */ if (pvBuf) RTMemFree(pvBuf); if (paFiles) { for (size_t i = 0; i < cFiles; ++i) if (paFiles[i].pszTestDigest) RTStrFree((char*)paFiles[i].pszTestDigest); RTMemFree(paFiles); } /* Delete the manifest file on failure */ if (RT_FAILURE(rc)) RTFileDelete(pszManifestFile); return rc; }