Changeset 39878 in vbox for trunk/src/VBox/Main
- Timestamp:
- Jan 25, 2012 4:30:07 PM (13 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/idl/VirtualBox.xidl
r39822 r39878 16214 16214 </desc> 16215 16215 <param name="path" type="wstring" dir="in"> 16216 <desc>The path of the extension pack tarball.</desc> 16216 <desc>The path of the extension pack tarball. This can optionally be 16217 followed by a "::SHA-256=hex-digit" of the tarball. </desc> 16217 16218 </param> 16218 16219 <param name="file" type="IExtPackFile" dir="return"> -
trunk/src/VBox/Main/include/ExtPackManagerImpl.h
r39661 r39878 44 44 HRESULT FinalConstruct(); 45 45 void FinalRelease(); 46 HRESULT initWithFile(const char *a_pszFile, c lass ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox);46 HRESULT initWithFile(const char *a_pszFile, const char *a_pszDigest, class ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox); 47 47 void uninit(); 48 48 RTMEMEF_NEW_AND_DELETE_OPERATORS(); -
trunk/src/VBox/Main/include/ExtPackUtil.h
r39661 r39878 127 127 128 128 int VBoxExtPackValidateMember(const char *pszName, RTVFSOBJTYPE enmType, RTVFSOBJ hVfsObj, char *pszError, size_t cbError); 129 int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss); 130 int VBoxExtPackValidateTarball(RTFILE hTarballFile, const char *pszExtPackName, const char *pszTarball, 131 char *pszError, size_t cbError, PRTMANIFEST phValidManifest, PRTVFSFILE phXmlFile); 129 int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss, PRTMANIFEST phFileManifest); 130 int VBoxExtPackValidateTarball(RTFILE hTarballFile, const char *pszExtPackName, 131 const char *pszTarball, const char *pszTarballDigest, 132 char *pszError, size_t cbError, 133 PRTMANIFEST phValidManifest, PRTVFSFILE phXmlFile, RTCString *pStrDigest); 132 134 133 135 -
trunk/src/VBox/Main/src-all/ExtPackManagerImpl.cpp
r39661 r39878 89 89 /** The path to the tarball. */ 90 90 Utf8Str strExtPackFile; 91 /** The SHA-256 hash of the file (as string). */ 92 Utf8Str strDigest; 91 93 /** The file handle of the extension pack file. */ 92 94 RTFILE hExtPackFile; … … 220 222 * @returns COM status code. 221 223 * @param a_pszFile The path to the extension pack file. 224 * @param a_pszDigest The SHA-256 digest of the file. Or an empty string. 222 225 * @param a_pExtPackMgr Pointer to the extension pack manager. 223 226 * @param a_pVirtualBox Pointer to the VirtualBox object. 224 227 */ 225 HRESULT ExtPackFile::initWithFile(const char *a_pszFile, ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox)228 HRESULT ExtPackFile::initWithFile(const char *a_pszFile, const char *a_pszDigest, ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox) 226 229 { 227 230 AutoInitSpan autoInitSpan(this); … … 237 240 m->strWhyUnusable = tr("ExtPack::init failed"); 238 241 m->strExtPackFile = a_pszFile; 242 m->strDigest = a_pszDigest; 239 243 m->hExtPackFile = NIL_RTFILE; 240 244 m->hOurManifest = NIL_RTMANIFEST; … … 276 280 char szError[8192]; 277 281 RTVFSFILE hXmlFile; 278 vrc = VBoxExtPackValidateTarball(m->hExtPackFile, NULL /*pszExtPackName*/, a_pszFile, 279 szError, sizeof(szError), &m->hOurManifest, &hXmlFile );282 vrc = VBoxExtPackValidateTarball(m->hExtPackFile, NULL /*pszExtPackName*/, a_pszFile, a_pszDigest, 283 szError, sizeof(szError), &m->hOurManifest, &hXmlFile, &m->strDigest); 280 284 if (RT_FAILURE(vrc)) 281 285 return initFailed(tr("%s"), szError); … … 549 553 RTVFSFSSTREAM hTarFss; 550 554 char szError[8192]; 551 int vrc = VBoxExtPackOpenTarFss(m->hExtPackFile, szError, sizeof(szError), &hTarFss );555 int vrc = VBoxExtPackOpenTarFss(m->hExtPackFile, szError, sizeof(szError), &hTarFss, NULL); 552 556 if (RT_SUCCESS(vrc)) 553 557 { … … 2025 2029 } 2026 2030 2027 STDMETHODIMP ExtPackManager::OpenExtPackFile(IN_BSTR a_bstrTarball , IExtPackFile **a_ppExtPackFile)2028 { 2029 CheckComArgNotNull(a_bstrTarball );2031 STDMETHODIMP ExtPackManager::OpenExtPackFile(IN_BSTR a_bstrTarballAndDigest, IExtPackFile **a_ppExtPackFile) 2032 { 2033 CheckComArgNotNull(a_bstrTarballAndDigest); 2030 2034 CheckComArgOutPointerValid(a_ppExtPackFile); 2031 Utf8Str strTarball(a_bstrTarball);2032 2035 AssertReturn(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON, E_UNEXPECTED); 2036 2037 /* The API can optionally take a ::SHA-256=<hex-digest> attribute at the 2038 end of the file name. This is just a temporary measure for 2039 backporting, in 4.2 we'll add another parameter to the method. */ 2040 Utf8Str strTarball; 2041 Utf8Str strDigest; 2042 Utf8Str strTarballAndDigest(a_bstrTarballAndDigest); 2043 size_t offSha256 = Utf8Str::npos; 2044 const char *pszFilename = RTPathFilename(strTarballAndDigest.c_str()); 2045 if (pszFilename) 2046 offSha256 = strTarballAndDigest.find("::SHA-256=", pszFilename - strTarballAndDigest.c_str()); 2047 if (offSha256 == Utf8Str::npos) 2048 strTarball = strTarballAndDigest; 2049 else 2050 { 2051 strTarball = strTarballAndDigest.substr(0, offSha256); 2052 strDigest = strTarballAndDigest.substr(offSha256 + sizeof("::SHA-256=") - 1); 2053 } 2033 2054 2034 2055 ComObjPtr<ExtPackFile> NewExtPackFile; 2035 2056 HRESULT hrc = NewExtPackFile.createObject(); 2036 2057 if (SUCCEEDED(hrc)) 2037 hrc = NewExtPackFile->initWithFile(strTarball.c_str(), this, m->pVirtualBox);2058 hrc = NewExtPackFile->initWithFile(strTarball.c_str(), strDigest.c_str(), this, m->pVirtualBox); 2038 2059 if (SUCCEEDED(hrc)) 2039 2060 NewExtPackFile.queryInterfaceTo(a_ppExtPackFile); … … 2599 2620 { 2600 2621 AssertReturn(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON, E_UNEXPECTED); 2601 RTCString const * const pStrName = &a_pExtPackFile->m->Desc.strName; 2602 RTCString const * const pStrTarball = &a_pExtPackFile->m->strExtPackFile; 2622 RTCString const * const pStrName = &a_pExtPackFile->m->Desc.strName; 2623 RTCString const * const pStrTarball = &a_pExtPackFile->m->strExtPackFile; 2624 RTCString const * const pStrTarballDigest = &a_pExtPackFile->m->strDigest; 2603 2625 2604 2626 AutoCaller autoCaller(this); … … 2631 2653 * even on failure, to be on the safe side). 2632 2654 */ 2633 /** @todo add a hash (SHA-256) of the tarball or maybe just the manifest. */2634 2655 hrc = runSetUidToRootHelper(a_pstrDisplayInfo, 2635 2656 "install", … … 2638 2659 "--name", pStrName->c_str(), 2639 2660 "--tarball", pStrTarball->c_str(), 2661 "--sha-256", pStrTarballDigest->c_str(), 2640 2662 pExtPack ? "--replace" : (const char *)NULL, 2641 2663 (const char *)NULL); -
trunk/src/VBox/Main/src-all/ExtPackUtil.cpp
r39180 r39878 5 5 6 6 /* 7 * Copyright (C) 2010-201 1Oracle Corporation7 * Copyright (C) 2010-2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 #include <iprt/param.h> 29 29 #include <iprt/path.h> 30 #include <iprt/sha.h> 30 31 #include <iprt/string.h> 31 32 #include <iprt/vfs.h> … … 784 785 return rc; 785 786 } 787 788 789 /** 790 * Verifies the file digest (if specified) and returns the SHA-256 of the file. 791 * 792 * @returns 793 * @param hFileManifest Manifest containing a SHA-256 digest of the file 794 * that was calculated as the file was processed. 795 * @param pszFileDigest SHA-256 digest of the file. 796 * @param pStrDigest Where to return the SHA-256 digest. Optional. 797 * @param pszError Where to write an error message on failure. 798 * @param cbError The size of the @a pszError buffer. 799 */ 800 static int vboxExtPackVerifyFileDigest(RTMANIFEST hFileManifest, const char *pszFileDigest, 801 RTCString *pStrDigest, char *pszError, size_t cbError) 802 { 803 /* 804 * Extract the SHA-256 entry for the extpack file. 805 */ 806 char szCalculatedDigest[RTSHA256_DIGEST_LEN + 1]; 807 int rc = RTManifestEntryQueryAttr(hFileManifest, "extpack", NULL /*no name*/, RTMANIFEST_ATTR_SHA256, 808 szCalculatedDigest, sizeof(szCalculatedDigest), NULL); 809 if (RT_SUCCESS(rc)) 810 { 811 /* 812 * Convert the two strings to binary form before comparing. 813 * We convert the calculated hash even if we don't have anything to 814 * compare with, just to validate it. 815 */ 816 uint8_t abCalculatedHash[RTSHA256_HASH_SIZE]; 817 rc = RTSha256FromString(szCalculatedDigest, abCalculatedHash); 818 if (RT_SUCCESS(rc)) 819 { 820 if ( pszFileDigest 821 && *pszFileDigest != '\0') 822 { 823 uint8_t abFileHash[RTSHA256_HASH_SIZE]; 824 rc = RTSha256FromString(pszFileDigest, abFileHash); 825 if (RT_SUCCESS(rc)) 826 { 827 if (memcmp(abFileHash, abCalculatedHash, sizeof(abFileHash))) 828 { 829 vboxExtPackSetError(pszError, cbError, "The extension pack file has changed (SHA-256 mismatch)"); 830 rc = VERR_NOT_EQUAL; 831 } 832 } 833 else 834 vboxExtPackSetError(pszError, cbError, "Bad SHA-256 '%s': %Rrc", szCalculatedDigest, rc); 835 } 836 837 /* 838 * Set the output hash on success. 839 */ 840 if (pStrDigest && RT_SUCCESS(rc)) 841 { 842 try 843 { 844 *pStrDigest = szCalculatedDigest; 845 } 846 catch (std::bad_alloc) 847 { 848 rc = VERR_NO_MEMORY; 849 } 850 } 851 } 852 else 853 vboxExtPackSetError(pszError, cbError, "Bad SHA-256 '%s': %Rrc", szCalculatedDigest, rc); 854 } 855 else 856 vboxExtPackSetError(pszError, cbError, "RTManifestEntryGetAttr: %Rrc", rc); 857 return rc; 858 } 859 786 860 787 861 … … 1044 1118 * @param cbError The size of the buffer @a pszError points to. 1045 1119 * @param phTarFss Where to return the filesystem stream handle. 1046 */ 1047 int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss) 1120 * @param phFileManifest Where to return a manifest where the tarball is 1121 * gettting hashed. The entry will be called 1122 * "extpack" and be ready when the file system 1123 * stream is at an end. Optional. 1124 */ 1125 int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss, PRTMANIFEST phFileManifest) 1048 1126 { 1049 1127 Assert(cbError > 0); … … 1064 1142 return vboxExtPackReturnError(rc, pszError, cbError, "RTVfsIoStrmFromRTFile failed: %Rrc", rc); 1065 1143 1066 RT VFSIOSTREAM hGunzipIos;1067 rc = RT ZipGzipDecompressIoStream(hTarballIos, 0 /*fFlags*/, &hGunzipIos);1144 RTMANIFEST hFileManifest = NIL_RTMANIFEST; 1145 rc = RTManifestCreate(0 /*fFlags*/, &hFileManifest); 1068 1146 if (RT_SUCCESS(rc)) 1069 1147 { 1070 RTVFS FSSTREAM hTarFss;1071 rc = RT ZipTarFsStreamFromIoStream(hGunzipIos, 0 /*fFlags*/, &hTarFss);1148 RTVFSIOSTREAM hPtIos; 1149 rc = RTManifestEntryAddPassthruIoStream(hFileManifest, hTarballIos, "extpack", RTMANIFEST_ATTR_SHA256, true /*read*/, &hPtIos); 1072 1150 if (RT_SUCCESS(rc)) 1073 1151 { 1074 RTVfsIoStrmRelease(hGunzipIos); 1075 RTVfsIoStrmRelease(hTarballIos); 1076 *phTarFss = hTarFss; 1077 return VINF_SUCCESS; 1078 } 1079 vboxExtPackSetError(pszError, cbError, "RTZipTarFsStreamFromIoStream failed: %Rrc", rc); 1080 RTVfsIoStrmRelease(hGunzipIos); 1152 RTVFSIOSTREAM hGunzipIos; 1153 rc = RTZipGzipDecompressIoStream(hPtIos, 0 /*fFlags*/, &hGunzipIos); 1154 if (RT_SUCCESS(rc)) 1155 { 1156 RTVFSFSSTREAM hTarFss; 1157 rc = RTZipTarFsStreamFromIoStream(hGunzipIos, 0 /*fFlags*/, &hTarFss); 1158 if (RT_SUCCESS(rc)) 1159 { 1160 RTVfsIoStrmRelease(hPtIos); 1161 RTVfsIoStrmRelease(hGunzipIos); 1162 RTVfsIoStrmRelease(hTarballIos); 1163 *phTarFss = hTarFss; 1164 if (phFileManifest) 1165 *phFileManifest = hFileManifest; 1166 else 1167 RTManifestRelease(hFileManifest); 1168 return VINF_SUCCESS; 1169 } 1170 1171 vboxExtPackSetError(pszError, cbError, "RTZipTarFsStreamFromIoStream failed: %Rrc", rc); 1172 RTVfsIoStrmRelease(hGunzipIos); 1173 } 1174 else 1175 vboxExtPackSetError(pszError, cbError, "RTZipGzipDecompressIoStream failed: %Rrc", rc); 1176 RTVfsIoStrmRelease(hPtIos); 1177 } 1178 else 1179 vboxExtPackSetError(pszError, cbError, "RTManifestEntryAddPassthruIoStream failed: %Rrc", rc); 1180 RTManifestRelease(hFileManifest); 1081 1181 } 1082 1182 else 1083 vboxExtPackSetError(pszError, cbError, "RTZipGzipDecompressIoStream failed: %Rrc", rc); 1183 vboxExtPackSetError(pszError, cbError, "RTManifestCreate failed: %Rrc", rc); 1184 1084 1185 RTVfsIoStrmRelease(hTarballIos); 1085 1186 return rc; … … 1102 1203 * @param pszTarball The name of the tarball in case we have to 1103 1204 * complain about something. 1205 * @param pszTarballDigest The SHA-256 digest of the tarball. Empty string 1206 * if no digest available. 1104 1207 * @param pszError Where to store an error message on failure. 1105 1208 * @param cbError The size of the buffer @a pszError points to. … … 1109 1212 * @param phXmlFile Where to optionally return the memorized XML 1110 1213 * file. 1111 * 1112 * @todo This function is a bit too long and should be split up if possible. 1113 */ 1114 int VBoxExtPackValidateTarball(RTFILE hTarballFile, const char *pszExtPackName, const char *pszTarball, 1115 char *pszError, size_t cbError, PRTMANIFEST phValidManifest, PRTVFSFILE phXmlFile) 1214 * @param pStrDigest Where to return the digest of the file. 1215 * Optional. 1216 */ 1217 int VBoxExtPackValidateTarball(RTFILE hTarballFile, const char *pszExtPackName, 1218 const char *pszTarball, const char *pszTarballDigest, 1219 char *pszError, size_t cbError, 1220 PRTMANIFEST phValidManifest, PRTVFSFILE phXmlFile, RTCString *pStrDigest) 1116 1221 { 1117 1222 /* … … 1129 1234 * Open the tar.gz filesystem stream and set up an manifest in-memory file. 1130 1235 */ 1131 RTVFSFSSTREAM hTarFss; 1132 int rc = VBoxExtPackOpenTarFss(hTarballFile, pszError, cbError, &hTarFss); 1236 RTMANIFEST hFileManifest; 1237 RTVFSFSSTREAM hTarFss; 1238 int rc = VBoxExtPackOpenTarFss(hTarballFile, pszError, cbError, &hTarFss, &hFileManifest); 1133 1239 if (RT_FAILURE(rc)) 1134 1240 return rc; … … 1141 1247 * Process the tarball (would be nice to move this to a function). 1142 1248 */ 1143 RTVFSFILE hXmlFile = NIL_RTVFSFILE;1144 RTVFSFILE hManifestFile = NIL_RTVFSFILE;1145 RTVFSFILE hSignatureFile = NIL_RTVFSFILE;1249 RTVFSFILE hXmlFile = NIL_RTVFSFILE; 1250 RTVFSFILE hManifestFile = NIL_RTVFSFILE; 1251 RTVFSFILE hSignatureFile = NIL_RTVFSFILE; 1146 1252 for (;;) 1147 1253 { … … 1210 1316 1211 1317 /* 1318 * Check the integrity of the tarball file. 1319 */ 1320 if (RT_SUCCESS(rc)) 1321 { 1322 RTVfsFsStrmRelease(hTarFss); 1323 hTarFss = NIL_RTVFSFSSTREAM; 1324 rc = vboxExtPackVerifyFileDigest(hFileManifest, pszTarballDigest, pStrDigest, pszError, cbError); 1325 } 1326 1327 /* 1212 1328 * If we've successfully processed the tarball, verify that the 1213 1329 * mandatory files are present. … … 1263 1379 vboxExtPackSetError(pszError, cbError, "RTManifestCreate failed: %Rrc", rc); 1264 1380 RTVfsFsStrmRelease(hTarFss); 1381 RTManifestRelease(hFileManifest); 1265 1382 1266 1383 return rc; -
trunk/src/VBox/Main/src-helper-apps/VBoxExtPackHelperApp.cpp
r39612 r39878 5 5 6 6 /* 7 * Copyright (C) 2010-201 1Oracle Corporation7 * Copyright (C) 2010-2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 34 34 #include <iprt/path.h> 35 35 #include <iprt/process.h> 36 #include <iprt/sha.h> 36 37 #include <iprt/string.h> 37 38 #include <iprt/stream.h> … … 254 255 { 255 256 char szError[8192]; 256 int rc = VBoxExtPackOpenTarFss(hTarballFile, szError, sizeof(szError), phTarFss );257 int rc = VBoxExtPackOpenTarFss(hTarballFile, szError, sizeof(szError), phTarFss, NULL); 257 258 if (RT_FAILURE(rc)) 258 259 { … … 597 598 * @param pszTarball The name of the tarball in case we have to 598 599 * complain about something. 600 * @param pszTarballDigest The SHA-256 digest of the tarball. 599 601 * @param phValidManifest Where to return the handle to fully validated 600 602 * the manifest for the extension pack. This … … 602 604 */ 603 605 static RTEXITCODE ValidateExtPackTarball(RTFILE hTarballFile, const char *pszExtPackName, const char *pszTarball, 604 PRTMANIFEST phValidManifest)606 const char *pszTarballDigest, PRTMANIFEST phValidManifest) 605 607 { 606 608 *phValidManifest = NIL_RTMANIFEST; 607 609 RTMsgInfo("Validating extension pack '%s' ('%s')...", pszTarball, pszExtPackName); 610 Assert(pszTarballDigest && *pszTarballDigest); 608 611 609 612 char szError[8192]; 610 int rc = VBoxExtPackValidateTarball(hTarballFile, pszExtPackName, pszTarball, 611 szError, sizeof(szError), phValidManifest, NULL /*phXmlFile*/ );613 int rc = VBoxExtPackValidateTarball(hTarballFile, pszExtPackName, pszTarball, pszTarballDigest, 614 szError, sizeof(szError), phValidManifest, NULL /*phXmlFile*/, NULL /*pStrDigest*/); 612 615 if (RT_FAILURE(rc)) 613 616 { … … 627 630 * @param pszCertDir The certificat directory. 628 631 * @param pszTarball The tarball name. 632 * @param pszTarballDigest The SHA-256 digest of the tarball. Empty string 633 * if no digest available. 629 634 * @param hTarballFile The handle to open the @a pszTarball file. 630 635 * @param hTarballFileOpt The tarball file handle (optional). … … 634 639 */ 635 640 static RTEXITCODE DoInstall2(const char *pszBaseDir, const char *pszCertDir, const char *pszTarball, 636 RTFILE hTarballFile, RTFILE hTarballFileOpt,641 const char *pszTarballDigest, RTFILE hTarballFile, RTFILE hTarballFileOpt, 637 642 const char *pszName, const char *pszMangledName, bool fReplace) 638 643 { … … 719 724 720 725 RTMANIFEST hValidManifest = NIL_RTMANIFEST; 721 RTEXITCODE rcExit = ValidateExtPackTarball(hTarballFile, pszName, pszTarball, &hValidManifest);726 RTEXITCODE rcExit = ValidateExtPackTarball(hTarballFile, pszName, pszTarball, pszTarballDigest, &hValidManifest); 722 727 if (rcExit == RTEXITCODE_SUCCESS) 723 728 rcExit = UnpackExtPack(hTarballFile, szTmpPath, hValidManifest, pszTarball); … … 783 788 { "--tarball", 't', RTGETOPT_REQ_STRING }, 784 789 { "--tarball-fd", 'd', RTGETOPT_REQ_UINT64 }, 785 { "--replace", 'r', RTGETOPT_REQ_NOTHING } 790 { "--replace", 'r', RTGETOPT_REQ_NOTHING }, 791 { "--sha-256", 's', RTGETOPT_REQ_STRING } 786 792 }; 787 793 RTGETOPTSTATE GetState; … … 790 796 return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOptInit failed: %Rrc\n", rc); 791 797 792 const char *pszBaseDir = NULL; 793 const char *pszCertDir = NULL; 794 const char *pszName = NULL; 795 const char *pszTarball = NULL; 796 RTFILE hTarballFileOpt = NIL_RTFILE; 797 bool fReplace = false; 798 const char *pszBaseDir = NULL; 799 const char *pszCertDir = NULL; 800 const char *pszName = NULL; 801 const char *pszTarball = NULL; 802 const char *pszTarballDigest = NULL; 803 RTFILE hTarballFileOpt = NIL_RTFILE; 804 bool fReplace = false; 798 805 RTGETOPTUNION ValueUnion; 799 806 int ch; … … 849 856 break; 850 857 858 case 's': 859 { 860 if (pszTarballDigest) 861 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --sha-256 options"); 862 pszTarballDigest = ValueUnion.psz; 863 864 uint8_t abDigest[RTSHA256_HASH_SIZE]; 865 rc = RTSha256FromString(pszTarballDigest, abDigest); 866 if (RT_FAILURE(rc)) 867 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Bad SHA-256 string: %Rrc", rc); 868 break; 869 } 870 851 871 case 'h': 852 872 case 'V': … … 865 885 if (!pszTarball) 866 886 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --tarball option"); 887 if (!pszTarballDigest) 888 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --sha-256 option"); 867 889 868 890 /* … … 878 900 if (RT_SUCCESS(rc)) 879 901 { 880 rcExit = DoInstall2(pszBaseDir, pszCertDir, pszTarball, hTarballFile, hTarballFileOpt,902 rcExit = DoInstall2(pszBaseDir, pszCertDir, pszTarball, pszTarballDigest, hTarballFile, hTarballFileOpt, 881 903 pszName, pstrMangledName->c_str(), fReplace); 882 904 RTFileClose(hTarballFile);
Note:
See TracChangeset
for help on using the changeset viewer.