Changeset 23499 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Oct 2, 2009 7:58:09 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/checksum/manifest.cpp
r21749 r23499 30 30 31 31 32 #include "iprt/manifest.h" 33 32 /******************************************************************************* 33 * Header Files * 34 *******************************************************************************/ 35 #include "internal/iprt.h" 36 #include <iprt/manifest.h> 37 38 #include <iprt/err.h> 39 #include <iprt/file.h> 40 #include <iprt/mem.h> 41 #include <iprt/path.h> 34 42 #include <iprt/sha1.h> 35 43 #include <iprt/stream.h> 36 44 #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> 45 43 46 44 47 /******************************************************************************* 45 48 * Structures and Typedefs * 46 49 *******************************************************************************/ 47 typedef struct RTFILELISTINT 50 /** 51 * Internal per file structure used by RTManifestVerify 52 */ 53 typedef struct RTMANIFESTFILEENTRY 48 54 { 49 55 char *pszManifestFile; 50 56 char *pszManifestDigest; 51 57 PRTMANIFESTTEST pTestPattern; 52 } RTFILELISTINT; 53 typedef RTFILELISTINT* PRTFILELISTINT; 54 55 /******************************************************************************* 56 * Public RTManifest interface * 57 *******************************************************************************/ 58 } RTMANIFESTFILEENTRY; 59 typedef RTMANIFESTFILEENTRY* PRTMANIFESTFILEENTRY; 60 61 58 62 59 63 RTR3DECL(int) RTManifestVerify(const char *pszManifestFile, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed) 60 64 { 61 65 /* Validate input */ 62 if (!pszManifestFile || !paTests) 63 { 64 AssertMsgFailed(("Must supply pszManifestFile and paTests!\n")); 65 return VERR_INVALID_PARAMETER; 66 } 66 AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER); 67 AssertPtrReturn(paTests, VERR_INVALID_POINTER); 68 AssertReturn(cTests > 0, VERR_INVALID_PARAMETER); 67 69 68 70 /* Open the manifest file */ … … 72 74 return rc; 73 75 74 PRTFILELISTINT pFileList = (PRTFILELISTINT)RTMemAllocZ(sizeof(RTFILELISTINT)*cTests); 75 if (!pFileList) 76 PRTMANIFESTFILEENTRY paFiles = (PRTMANIFESTFILEENTRY)RTMemTmpAllocZ(sizeof(RTMANIFESTFILEENTRY) * cTests); 77 if (!paFiles) 78 { 79 RTStrmClose(pStream); 76 80 return VERR_NO_MEMORY; 81 } 82 77 83 /* Fill our compare list */ 78 for (size_t i =0; i < cTests; ++i)79 p FileList[i].pTestPattern = &paTests[i];84 for (size_t i = 0; i < cTests; ++i) 85 paFiles[i].pTestPattern = &paTests[i]; 80 86 81 87 /* Parse the manifest file line by line */ 82 char pszLine[1024];83 do84 { 85 rc = RTStrmGetLine(pStream, pszLine, 1024);88 char szLine[1024]; 89 for (;;) 90 { 91 rc = RTStrmGetLine(pStream, szLine, sizeof(szLine)); 86 92 if (RT_FAILURE(rc)) 87 93 break; 88 size_t cbCount = strlen(pszLine); 94 size_t cch = strlen(szLine); 95 89 96 /* Skip empty lines */ 90 if (c bCount== 0)97 if (cch == 0) 91 98 continue; 99 100 /** @todo r=bird: 101 * -# The SHA1 test should probably include a blank space check. 102 * -# If there is a specific order to the elements in the string, it would be 103 * good if the delimiter searching checked for it. 104 * -# Deal with filenames containing delimiter characters. 105 */ 106 92 107 /* 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'))108 if ( cch < 4 109 || !( szLine[0] == 'S' 110 && szLine[1] == 'H' 111 && szLine[2] == 'A' 112 && szLine[3] == '1')) 98 113 { 99 114 /* Digest unsupported */ … … 101 116 break; 102 117 } 118 103 119 /* Try to find the filename */ 104 char *pszNameStart = RTStrStr(pszLine, "(");120 char *pszNameStart = strchr(szLine, '('); 105 121 if (!pszNameStart) 106 122 { … … 108 124 break; 109 125 } 110 char *pszNameEnd = RTStrStr(pszLine, ")");126 char *pszNameEnd = strchr(szLine, ')'); 111 127 if (!pszNameEnd) 112 128 { … … 114 130 break; 115 131 } 132 116 133 /* Copy the filename part */ 117 size_t len = pszNameEnd-pszNameStart - 1;118 char * pszName = (char*)RTMemAlloc(len+1);134 size_t cchName = pszNameEnd - pszNameStart - 1; 135 char *pszName = (char *)RTMemTmpAlloc(cchName + 1); 119 136 if (!pszName) 120 137 { … … 122 139 break; 123 140 } 124 memcpy(pszName, pszNameStart + 1, len); 125 pszName[len] = '\0'; 141 memcpy(pszName, pszNameStart + 1, cchName); 142 pszName[cchName] = '\0'; 143 126 144 /* Try to find the digest sum */ 127 char *pszDigestStart = RTStrStr(pszLine, "=") + 1;145 char *pszDigestStart = strchr(szLine, '='); 128 146 if (!pszDigestStart) 129 147 { 148 RTMemTmpFree(pszName); 130 149 rc = VERR_MANIFEST_WRONG_FILE_FORMAT; 131 150 break; 132 151 } 133 char *pszDigest = pszDigestStart; 152 char *pszDigest = ++pszDigestStart; 153 134 154 /* Check our file list against the extracted data */ 135 155 bool fFound = false; 136 for (size_t i =0; i < cTests; ++i)137 { 138 if (!RTStrCmp(RTPathFilename(p FileList[i].pTestPattern->pszTestFile), RTStrStrip(pszName)))156 for (size_t i = 0; i < cTests; ++i) 157 { 158 if (!RTStrCmp(RTPathFilename(paFiles[i].pTestPattern->pszTestFile), RTStrStrip(pszName))) 139 159 { 140 160 /* Add the data of the manifest file to the file list */ 161 paFiles[i].pszManifestFile = RTStrDup(RTStrStrip(pszName)); 162 paFiles[i].pszManifestDigest = RTStrDup(RTStrStrip(pszDigest)); 141 163 fFound = true; 142 pFileList[i].pszManifestFile = RTStrDup(RTStrStrip(pszName));143 pFileList[i].pszManifestDigest = RTStrDup(RTStrStrip(pszDigest));144 164 break; 145 165 } 146 166 } 147 RT StrFree(pszName);167 RTMemTmpFree(pszName); 148 168 if (!fFound) 149 169 { … … 153 173 } 154 174 } 155 while (1);156 175 RTStrmClose(pStream); 157 176 158 if ( rc == VINF_SUCCESS ||159 rc == VERR_EOF)177 if ( rc == VINF_SUCCESS 178 || rc == VERR_EOF) 160 179 { 161 180 rc = VINF_SUCCESS; 162 for (size_t i =0; i < cTests; ++i)181 for (size_t i = 0; i < cTests; ++i) 163 182 { 164 183 /* If there is an entry in the file list, which hasn't an 165 184 * equivalent in the manifest file, its an error. */ 166 if ( !pFileList[i].pszManifestFile ||167 !pFileList[i].pszManifestDigest)185 if ( !paFiles[i].pszManifestFile 186 || !paFiles[i].pszManifestDigest) 168 187 { 169 188 rc = VERR_MANIFEST_FILE_MISMATCH; 170 189 break; 171 190 } 191 172 192 /* Do the manifest SHA1 digest match against the actual digest? */ 173 if (RTStrICmp(p FileList[i].pszManifestDigest, pFileList[i].pTestPattern->pszTestDigest))193 if (RTStrICmp(paFiles[i].pszManifestDigest, paFiles[i].pTestPattern->pszTestDigest)) 174 194 { 175 195 if (piFailed) … … 182 202 183 203 /* Cleanup */ 184 for (size_t i =0; i < cTests; ++i)185 { 186 if (p FileList[i].pszManifestFile)187 RTStrFree (pFileList[i].pszManifestFile);188 if (p FileList[i].pszManifestDigest)189 RTStrFree (pFileList[i].pszManifestDigest);190 } 191 RTMem Free(pFileList);204 for (size_t i = 0; i < cTests; ++i) 205 { 206 if (paFiles[i].pszManifestFile) 207 RTStrFree(paFiles[i].pszManifestFile); 208 if (paFiles[i].pszManifestDigest) 209 RTStrFree(paFiles[i].pszManifestDigest); 210 } 211 RTMemTmpFree(paFiles); 192 212 193 213 return rc; 194 214 } 195 215 216 196 217 RTR3DECL(int) RTManifestVerifyFiles(const char *pszManifestFile, const char * const *papszFiles, size_t cFiles, size_t *piFailed) 197 218 { 198 219 /* Validate input */ 199 if (!pszManifestFile || !papszFiles) 200 { 201 AssertMsgFailed(("Must supply pszManifestFile and papszFiles!\n")); 202 return VERR_INVALID_PARAMETER; 203 } 220 AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER); 221 AssertPtrReturn(papszFiles, VERR_INVALID_POINTER); 204 222 205 223 /* Create our compare list */ 206 PRTMANIFESTTEST p FileList = (PRTMANIFESTTEST)RTMemAllocZ(sizeof(RTMANIFESTTEST)*cFiles);207 if (!p FileList)224 PRTMANIFESTTEST paFiles = (PRTMANIFESTTEST)RTMemTmpAllocZ(sizeof(RTMANIFESTTEST) * cFiles); 225 if (!paFiles) 208 226 return VERR_NO_MEMORY; 209 227 228 /* Fill our compare list */ 210 229 int rc = VINF_SUCCESS; 211 /* Fill our compare list */ 212 for (size_t i=0; i < cFiles; ++i) 230 for (size_t i = 0; i < cFiles; ++i) 213 231 { 214 232 char *pszDigest; … … 216 234 if (RT_FAILURE(rc)) 217 235 break; 218 pFileList[i].pszTestFile = (char*)papszFiles[i]; 219 pFileList[i].pszTestDigest = pszDigest; 220 } 221 /* Do the verify */ 236 paFiles[i].pszTestFile = (char*)papszFiles[i]; 237 paFiles[i].pszTestDigest = pszDigest; 238 } 239 240 /* Do the verification */ 222 241 if (RT_SUCCESS(rc)) 223 rc = RTManifestVerify(pszManifestFile, p FileList, cFiles, piFailed);242 rc = RTManifestVerify(pszManifestFile, paFiles, cFiles, piFailed); 224 243 225 244 /* Cleanup */ 226 for (size_t i =0; i < cFiles; ++i)227 { 228 if (p FileList[i].pszTestDigest)229 RTStrFree(p FileList[i].pszTestDigest);230 } 231 RTMem Free(pFileList);245 for (size_t i = 0; i < cFiles; ++i) 246 { 247 if (paFiles[i].pszTestDigest) 248 RTStrFree(paFiles[i].pszTestDigest); 249 } 250 RTMemTmpFree(paFiles); 232 251 233 252 return rc; 234 253 } 235 254 255 236 256 RTR3DECL(int) RTManifestWriteFiles(const char *pszManifestFile, const char * const *papszFiles, size_t cFiles) 237 257 { 238 258 /* Validate input */ 239 if (!pszManifestFile || !papszFiles) 240 { 241 AssertMsgFailed(("Must supply pszManifestFile and papszFiles!\n")); 242 return VERR_INVALID_PARAMETER; 243 } 259 AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER); 260 AssertPtrReturn(papszFiles, VERR_INVALID_POINTER); 244 261 245 262 /* Open a file to stream in */ … … 249 266 return rc; 250 267 251 for (size_t i =0; i < cFiles; ++i)268 for (size_t i = 0; i < cFiles; ++i) 252 269 { 253 270 /* Calculate the SHA1 digest of every file */ … … 256 273 if (RT_FAILURE(rc)) 257 274 break; 275 258 276 /* Add the entry to the manifest file */ 259 int c bRet= RTStrmPrintf(pStream, "SHA1 (%s)= %s\n", RTPathFilename(papszFiles[i]), pszDigest);277 int cch = RTStrmPrintf(pStream, "SHA1 (%s)= %s\n", RTPathFilename(papszFiles[i]), pszDigest); 260 278 RTStrFree(pszDigest); 261 if (RT_UNLIKELY(c bRet< 0))279 if (RT_UNLIKELY(cch < 0)) 262 280 { 263 281 rc = VERR_INTERNAL_ERROR; … … 265 283 } 266 284 } 267 RTStrmClose(pStream); 285 int rc2 = RTStrmClose(pStream); 286 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 287 rc2 = rc; 288 268 289 /* Delete the manifest file on failure */ 269 290 if (RT_FAILURE(rc))
Note:
See TracChangeset
for help on using the changeset viewer.