VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/checksum/manifest.cpp@ 23482

Last change on this file since 23482 was 21749, checked in by vboxsync, 16 years ago

Runtime: optimization hint

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: manifest.cpp 21749 2009-07-21 13:06:29Z vboxsync $ */
2/** @file
3 * IPRT - Manifest file handling.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32#include "iprt/manifest.h"
33
34#include <iprt/sha1.h>
35#include <iprt/stream.h>
36#include <iprt/string.h>
37#include <iprt/path.h>
38#include <iprt/file.h>
39#include <iprt/mem.h>
40#include <iprt/err.h>
41
42#include <stdlib.h>
43
44/*******************************************************************************
45* Structures and Typedefs *
46*******************************************************************************/
47typedef struct RTFILELISTINT
48{
49 char *pszManifestFile;
50 char *pszManifestDigest;
51 PRTMANIFESTTEST pTestPattern;
52} RTFILELISTINT;
53typedef RTFILELISTINT* PRTFILELISTINT;
54
55/*******************************************************************************
56* Public RTManifest interface *
57*******************************************************************************/
58
59RTR3DECL(int) RTManifestVerify(const char *pszManifestFile, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed)
60{
61 /* Validate input */
62 if (!pszManifestFile || !paTests)
63 {
64 AssertMsgFailed(("Must supply pszManifestFile and paTests!\n"));
65 return VERR_INVALID_PARAMETER;
66 }
67
68 /* Open the manifest file */
69 PRTSTREAM pStream;
70 int rc = RTStrmOpen(pszManifestFile, "r", &pStream);
71 if (RT_FAILURE(rc))
72 return rc;
73
74 PRTFILELISTINT pFileList = (PRTFILELISTINT)RTMemAllocZ(sizeof(RTFILELISTINT)*cTests);
75 if (!pFileList)
76 return VERR_NO_MEMORY;
77 /* Fill our compare list */
78 for (size_t i=0; i < cTests; ++i)
79 pFileList[i].pTestPattern = &paTests[i];
80
81 /* Parse the manifest file line by line */
82 char pszLine[1024];
83 do
84 {
85 rc = RTStrmGetLine(pStream, pszLine, 1024);
86 if (RT_FAILURE(rc))
87 break;
88 size_t cbCount = strlen(pszLine);
89 /* Skip empty lines */
90 if (cbCount == 0)
91 continue;
92 /* Check for the digest algorithm */
93 if (cbCount < 4 ||
94 !(pszLine[0] == 'S' &&
95 pszLine[1] == 'H' &&
96 pszLine[2] == 'A' &&
97 pszLine[3] == '1'))
98 {
99 /* Digest unsupported */
100 rc = VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE;
101 break;
102 }
103 /* Try to find the filename */
104 char *pszNameStart = RTStrStr(pszLine, "(");
105 if (!pszNameStart)
106 {
107 rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
108 break;
109 }
110 char *pszNameEnd = RTStrStr(pszLine, ")");
111 if (!pszNameEnd)
112 {
113 rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
114 break;
115 }
116 /* Copy the filename part */
117 size_t len = pszNameEnd-pszNameStart - 1;
118 char* pszName = (char*)RTMemAlloc(len+1);
119 if (!pszName)
120 {
121 rc = VERR_NO_MEMORY;
122 break;
123 }
124 memcpy(pszName, pszNameStart + 1, len);
125 pszName[len] = '\0';
126 /* Try to find the digest sum */
127 char *pszDigestStart = RTStrStr(pszLine, "=") + 1;
128 if (!pszDigestStart)
129 {
130 rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
131 break;
132 }
133 char *pszDigest = pszDigestStart;
134 /* Check our file list against the extracted data */
135 bool fFound = false;
136 for (size_t i=0; i < cTests; ++i)
137 {
138 if (!RTStrCmp(RTPathFilename(pFileList[i].pTestPattern->pszTestFile), RTStrStrip(pszName)))
139 {
140 /* Add the data of the manifest file to the file list */
141 fFound = true;
142 pFileList[i].pszManifestFile = RTStrDup(RTStrStrip(pszName));
143 pFileList[i].pszManifestDigest = RTStrDup(RTStrStrip(pszDigest));
144 break;
145 }
146 }
147 RTStrFree(pszName);
148 if (!fFound)
149 {
150 /* There have to be an entry in the file list */
151 rc = VERR_MANIFEST_FILE_MISMATCH;
152 break;
153 }
154 }
155 while (1);
156 RTStrmClose(pStream);
157
158 if (rc == VINF_SUCCESS ||
159 rc == VERR_EOF)
160 {
161 rc = VINF_SUCCESS;
162 for (size_t i=0; i < cTests; ++i)
163 {
164 /* If there is an entry in the file list, which hasn't an
165 * equivalent in the manifest file, its an error. */
166 if (!pFileList[i].pszManifestFile ||
167 !pFileList[i].pszManifestDigest)
168 {
169 rc = VERR_MANIFEST_FILE_MISMATCH;
170 break;
171 }
172 /* Do the manifest SHA1 digest match against the actual digest? */
173 if (RTStrICmp(pFileList[i].pszManifestDigest, pFileList[i].pTestPattern->pszTestDigest))
174 {
175 if (piFailed)
176 *piFailed = i;
177 rc = VERR_MANIFEST_DIGEST_MISMATCH;
178 break;
179 }
180 }
181 }
182
183 /* Cleanup */
184 for (size_t i=0; i < cTests; ++i)
185 {
186 if (pFileList[i].pszManifestFile)
187 RTStrFree (pFileList[i].pszManifestFile);
188 if (pFileList[i].pszManifestDigest)
189 RTStrFree (pFileList[i].pszManifestDigest);
190 }
191 RTMemFree(pFileList);
192
193 return rc;
194}
195
196RTR3DECL(int) RTManifestVerifyFiles(const char *pszManifestFile, const char * const *papszFiles, size_t cFiles, size_t *piFailed)
197{
198 /* Validate input */
199 if (!pszManifestFile || !papszFiles)
200 {
201 AssertMsgFailed(("Must supply pszManifestFile and papszFiles!\n"));
202 return VERR_INVALID_PARAMETER;
203 }
204
205 /* Create our compare list */
206 PRTMANIFESTTEST pFileList = (PRTMANIFESTTEST)RTMemAllocZ(sizeof(RTMANIFESTTEST)*cFiles);
207 if (!pFileList)
208 return VERR_NO_MEMORY;
209
210 int rc = VINF_SUCCESS;
211 /* Fill our compare list */
212 for (size_t i=0; i < cFiles; ++i)
213 {
214 char *pszDigest;
215 rc = RTSha1Digest(papszFiles[i], &pszDigest);
216 if (RT_FAILURE(rc))
217 break;
218 pFileList[i].pszTestFile = (char*)papszFiles[i];
219 pFileList[i].pszTestDigest = pszDigest;
220 }
221 /* Do the verify */
222 if (RT_SUCCESS(rc))
223 rc = RTManifestVerify(pszManifestFile, pFileList, cFiles, piFailed);
224
225 /* Cleanup */
226 for (size_t i=0; i < cFiles; ++i)
227 {
228 if (pFileList[i].pszTestDigest)
229 RTStrFree(pFileList[i].pszTestDigest);
230 }
231 RTMemFree(pFileList);
232
233 return rc;
234}
235
236RTR3DECL(int) RTManifestWriteFiles(const char *pszManifestFile, const char * const *papszFiles, size_t cFiles)
237{
238 /* Validate input */
239 if (!pszManifestFile || !papszFiles)
240 {
241 AssertMsgFailed(("Must supply pszManifestFile and papszFiles!\n"));
242 return VERR_INVALID_PARAMETER;
243 }
244
245 /* Open a file to stream in */
246 PRTSTREAM pStream;
247 int rc = RTStrmOpen(pszManifestFile, "w", &pStream);
248 if (RT_FAILURE(rc))
249 return rc;
250
251 for (size_t i=0; i < cFiles; ++i)
252 {
253 /* Calculate the SHA1 digest of every file */
254 char *pszDigest;
255 rc = RTSha1Digest(papszFiles[i], &pszDigest);
256 if (RT_FAILURE(rc))
257 break;
258 /* Add the entry to the manifest file */
259 int cbRet = RTStrmPrintf(pStream, "SHA1 (%s)= %s\n", RTPathFilename(papszFiles[i]), pszDigest);
260 RTStrFree(pszDigest);
261 if (RT_UNLIKELY(cbRet < 0))
262 {
263 rc = VERR_INTERNAL_ERROR;
264 break;
265 }
266 }
267 RTStrmClose(pStream);
268 /* Delete the manifest file on failure */
269 if (RT_FAILURE(rc))
270 RTFileDelete(pszManifestFile);
271
272 return rc;
273}
274
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette