manifest.cpp revision e9b9aa0cb0196b30917a7756bc124db5e7e9ca76
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync/* $Id$ */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync/** @file
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * IPRT - Manifest file handling.
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync/*
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * Copyright (C) 2009 Sun Microsystems, Inc.
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync *
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * available from http://www.virtualbox.org. This file is free software;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * General Public License (GPL) as published by the Free Software
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync *
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * The contents of this file may alternatively be used under the terms
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * of the Common Development and Distribution License Version 1.0
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * VirtualBox OSE distribution, in which case the provisions of the
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * CDDL are applicable instead of those of the GPL.
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync *
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * You may elect to license modified versions of this file under the
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * terms and conditions of either the GPL or the CDDL or both.
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync *
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * additional information or have any questions.
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync/*******************************************************************************
70dd77b2f7732defac9d929109f20d92676f0570vboxsync* Header Files *
70dd77b2f7732defac9d929109f20d92676f0570vboxsync*******************************************************************************/
70dd77b2f7732defac9d929109f20d92676f0570vboxsync#include "internal/iprt.h"
70dd77b2f7732defac9d929109f20d92676f0570vboxsync#include <iprt/manifest.h>
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync#include <iprt/err.h>
70dd77b2f7732defac9d929109f20d92676f0570vboxsync#include <iprt/file.h>
70dd77b2f7732defac9d929109f20d92676f0570vboxsync#include <iprt/mem.h>
70dd77b2f7732defac9d929109f20d92676f0570vboxsync#include <iprt/path.h>
e9b9aa0cb0196b30917a7756bc124db5e7e9ca76vboxsync#include <iprt/sha.h>
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync#include <iprt/stream.h>
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync#include <iprt/string.h>
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync/*******************************************************************************
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync* Structures and Typedefs *
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync*******************************************************************************/
70dd77b2f7732defac9d929109f20d92676f0570vboxsync/**
70dd77b2f7732defac9d929109f20d92676f0570vboxsync * Internal per file structure used by RTManifestVerify
70dd77b2f7732defac9d929109f20d92676f0570vboxsync */
70dd77b2f7732defac9d929109f20d92676f0570vboxsynctypedef struct RTMANIFESTFILEENTRY
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync{
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync char *pszManifestFile;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync char *pszManifestDigest;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync PRTMANIFESTTEST pTestPattern;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync} RTMANIFESTFILEENTRY;
70dd77b2f7732defac9d929109f20d92676f0570vboxsynctypedef RTMANIFESTFILEENTRY* PRTMANIFESTFILEENTRY;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
0aa6851583f4cb074ccc163d5b53948b9429ab77vboxsyncRTR3DECL(int) RTManifestVerify(const char *pszManifestFile, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync{
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Validate input */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync AssertPtrReturn(paTests, VERR_INVALID_POINTER);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync AssertReturn(cTests > 0, VERR_INVALID_PARAMETER);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Open the manifest file */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync PRTSTREAM pStream;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync int rc = RTStrmOpen(pszManifestFile, "r", &pStream);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (RT_FAILURE(rc))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync return rc;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync PRTMANIFESTFILEENTRY paFiles = (PRTMANIFESTFILEENTRY)RTMemTmpAllocZ(sizeof(RTMANIFESTFILEENTRY) * cTests);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (!paFiles)
70dd77b2f7732defac9d929109f20d92676f0570vboxsync {
70dd77b2f7732defac9d929109f20d92676f0570vboxsync RTStrmClose(pStream);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync return VERR_NO_MEMORY;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Fill our compare list */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync for (size_t i = 0; i < cTests; ++i)
70dd77b2f7732defac9d929109f20d92676f0570vboxsync paFiles[i].pTestPattern = &paTests[i];
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Parse the manifest file line by line */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync char szLine[1024];
70dd77b2f7732defac9d929109f20d92676f0570vboxsync for (;;)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
70dd77b2f7732defac9d929109f20d92676f0570vboxsync rc = RTStrmGetLine(pStream, szLine, sizeof(szLine));
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (RT_FAILURE(rc))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync size_t cch = strlen(szLine);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Skip empty lines */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (cch == 0)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync continue;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync /** @todo r=bird:
70dd77b2f7732defac9d929109f20d92676f0570vboxsync * -# The SHA1 test should probably include a blank space check.
70dd77b2f7732defac9d929109f20d92676f0570vboxsync * -# If there is a specific order to the elements in the string, it would be
70dd77b2f7732defac9d929109f20d92676f0570vboxsync * good if the delimiter searching checked for it.
70dd77b2f7732defac9d929109f20d92676f0570vboxsync * -# Deal with filenames containing delimiter characters.
70dd77b2f7732defac9d929109f20d92676f0570vboxsync */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Check for the digest algorithm */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if ( cch < 4
70dd77b2f7732defac9d929109f20d92676f0570vboxsync || !( szLine[0] == 'S'
70dd77b2f7732defac9d929109f20d92676f0570vboxsync && szLine[1] == 'H'
70dd77b2f7732defac9d929109f20d92676f0570vboxsync && szLine[2] == 'A'
70dd77b2f7732defac9d929109f20d92676f0570vboxsync && szLine[3] == '1'))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Digest unsupported */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Try to find the filename */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync char *pszNameStart = strchr(szLine, '(');
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (!pszNameStart)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync char *pszNameEnd = strchr(szLine, ')');
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (!pszNameEnd)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Copy the filename part */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync size_t cchName = pszNameEnd - pszNameStart - 1;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync char *pszName = (char *)RTMemTmpAlloc(cchName + 1);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (!pszName)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_NO_MEMORY;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync memcpy(pszName, pszNameStart + 1, cchName);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync pszName[cchName] = '\0';
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Try to find the digest sum */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync char *pszDigestStart = strchr(szLine, '=');
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (!pszDigestStart)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
70dd77b2f7732defac9d929109f20d92676f0570vboxsync RTMemTmpFree(pszName);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync char *pszDigest = ++pszDigestStart;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Check our file list against the extracted data */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync bool fFound = false;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync for (size_t i = 0; i < cTests; ++i)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (!RTStrCmp(RTPathFilename(paFiles[i].pTestPattern->pszTestFile), RTStrStrip(pszName)))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Add the data of the manifest file to the file list */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync paFiles[i].pszManifestFile = RTStrDup(RTStrStrip(pszName));
70dd77b2f7732defac9d929109f20d92676f0570vboxsync paFiles[i].pszManifestDigest = RTStrDup(RTStrStrip(pszDigest));
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync fFound = true;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync RTMemTmpFree(pszName);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (!fFound)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* There have to be an entry in the file list */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_MANIFEST_FILE_MISMATCH;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync RTStrmClose(pStream);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if ( rc == VINF_SUCCESS
70dd77b2f7732defac9d929109f20d92676f0570vboxsync || rc == VERR_EOF)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VINF_SUCCESS;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync for (size_t i = 0; i < cTests; ++i)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* If there is an entry in the file list, which hasn't an
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync * equivalent in the manifest file, its an error. */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if ( !paFiles[i].pszManifestFile
70dd77b2f7732defac9d929109f20d92676f0570vboxsync || !paFiles[i].pszManifestDigest)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_MANIFEST_FILE_MISMATCH;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Do the manifest SHA1 digest match against the actual digest? */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (RTStrICmp(paFiles[i].pszManifestDigest, paFiles[i].pTestPattern->pszTestDigest))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
0aa6851583f4cb074ccc163d5b53948b9429ab77vboxsync if (piFailed)
0aa6851583f4cb074ccc163d5b53948b9429ab77vboxsync *piFailed = i;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_MANIFEST_DIGEST_MISMATCH;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Cleanup */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync for (size_t i = 0; i < cTests; ++i)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (paFiles[i].pszManifestFile)
70dd77b2f7732defac9d929109f20d92676f0570vboxsync RTStrFree(paFiles[i].pszManifestFile);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (paFiles[i].pszManifestDigest)
70dd77b2f7732defac9d929109f20d92676f0570vboxsync RTStrFree(paFiles[i].pszManifestDigest);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync RTMemTmpFree(paFiles);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync return rc;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync}
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
0aa6851583f4cb074ccc163d5b53948b9429ab77vboxsyncRTR3DECL(int) RTManifestVerifyFiles(const char *pszManifestFile, const char * const *papszFiles, size_t cFiles, size_t *piFailed)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync{
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Validate input */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync AssertPtrReturn(papszFiles, VERR_INVALID_POINTER);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Create our compare list */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync PRTMANIFESTTEST paFiles = (PRTMANIFESTTEST)RTMemTmpAllocZ(sizeof(RTMANIFESTTEST) * cFiles);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (!paFiles)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync return VERR_NO_MEMORY;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Fill our compare list */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync int rc = VINF_SUCCESS;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync for (size_t i = 0; i < cFiles; ++i)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync char *pszDigest;
6bd05d07ef300e64cd44b5346c22f51ac972d460vboxsync rc = RTSha1Digest(papszFiles[i], &pszDigest);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (RT_FAILURE(rc))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync paFiles[i].pszTestFile = (char*)papszFiles[i];
70dd77b2f7732defac9d929109f20d92676f0570vboxsync paFiles[i].pszTestDigest = pszDigest;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync /* Do the verification */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (RT_SUCCESS(rc))
70dd77b2f7732defac9d929109f20d92676f0570vboxsync rc = RTManifestVerify(pszManifestFile, paFiles, cFiles, piFailed);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Cleanup */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync for (size_t i = 0; i < cFiles; ++i)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (paFiles[i].pszTestDigest)
70dd77b2f7732defac9d929109f20d92676f0570vboxsync RTStrFree(paFiles[i].pszTestDigest);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync RTMemTmpFree(paFiles);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync return rc;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync}
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
0aa6851583f4cb074ccc163d5b53948b9429ab77vboxsyncRTR3DECL(int) RTManifestWriteFiles(const char *pszManifestFile, const char * const *papszFiles, size_t cFiles)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync{
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Validate input */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync AssertPtrReturn(papszFiles, VERR_INVALID_POINTER);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Open a file to stream in */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync PRTSTREAM pStream;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync int rc = RTStrmOpen(pszManifestFile, "w", &pStream);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (RT_FAILURE(rc))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync return rc;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
70dd77b2f7732defac9d929109f20d92676f0570vboxsync for (size_t i = 0; i < cFiles; ++i)
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Calculate the SHA1 digest of every file */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync char *pszDigest;
6bd05d07ef300e64cd44b5346c22f51ac972d460vboxsync rc = RTSha1Digest(papszFiles[i], &pszDigest);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (RT_FAILURE(rc))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Add the entry to the manifest file */
70dd77b2f7732defac9d929109f20d92676f0570vboxsync int cch = RTStrmPrintf(pStream, "SHA1 (%s)= %s\n", RTPathFilename(papszFiles[i]), pszDigest);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync RTStrFree(pszDigest);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (RT_UNLIKELY(cch < 0))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync {
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync rc = VERR_INTERNAL_ERROR;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync break;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync }
70dd77b2f7732defac9d929109f20d92676f0570vboxsync int rc2 = RTStrmClose(pStream);
70dd77b2f7732defac9d929109f20d92676f0570vboxsync if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
70dd77b2f7732defac9d929109f20d92676f0570vboxsync rc2 = rc;
70dd77b2f7732defac9d929109f20d92676f0570vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync /* Delete the manifest file on failure */
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync if (RT_FAILURE(rc))
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync RTFileDelete(pszManifestFile);
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync return rc;
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync}
c40afa339b10a23d6fffcbeb7d4572bb494685f0vboxsync