diff options
Diffstat (limited to 'src/main/cpp/blaze.cc')
-rw-r--r-- | src/main/cpp/blaze.cc | 151 |
1 files changed, 125 insertions, 26 deletions
diff --git a/src/main/cpp/blaze.cc b/src/main/cpp/blaze.cc index 8c85bb62d0..d28d320be9 100644 --- a/src/main/cpp/blaze.cc +++ b/src/main/cpp/blaze.cc @@ -249,19 +249,93 @@ class GrpcBlazeServer : public BlazeServer { //////////////////////////////////////////////////////////////////////// // Logic -// A devtools_ijar::ZipExtractorProcessor to extract the InstallKeyFile -class GetInstallKeyFileProcessor : public devtools_ijar::ZipExtractorProcessor { +// A devtools_ijar::ZipExtractorProcessor that has a pure version of Accept. +class PureZipExtractorProcessor : public devtools_ijar::ZipExtractorProcessor { + public: + virtual ~PureZipExtractorProcessor() {} + + // Like devtools_ijar::ZipExtractorProcessor::Accept, but is guaranteed to not + // have side-effects. + virtual bool AcceptPure(const char *filename, + const devtools_ijar::u4 attr) const = 0; +}; + +// A PureZipExtractorProcessor that adds the names of all the files ZIP up in +// the Blaze binary to the given vector. +class NoteAllFilesZipProcessor : public PureZipExtractorProcessor { + public: + explicit NoteAllFilesZipProcessor(std::vector<std::string>* files) + : files_(files) {} + + bool AcceptPure(const char *filename, + const devtools_ijar::u4 attr) const override { + return false; + } + + bool Accept(const char *filename, const devtools_ijar::u4 attr) override { + files_->push_back(filename); + return false; + } + + void Process(const char *filename, const devtools_ijar::u4 attr, + const devtools_ijar::u1 *data, const size_t size) override { + die(blaze_exit_code::INTERNAL_ERROR, + "NoteAllFilesZipProcessor::Process shouldn't be called"); + } + private: + std::vector<std::string>* files_; +}; + +// A devtools_ijar::ZipExtractorProcessor that processes the ZIP entries using +// the given PureZipExtractorProcessors. +class CompoundZipProcessor : public devtools_ijar::ZipExtractorProcessor { + public: + explicit CompoundZipProcessor( + const vector<PureZipExtractorProcessor*>& processors) + : processors_(processors) {} + + bool Accept(const char *filename, const devtools_ijar::u4 attr) override { + bool should_accept = false; + for (auto* processor : processors_) { + if (processor->Accept(filename, attr)) { + // ZipExtractorProcessor::Accept is allowed to be side-effectful, so + // we don't want to break out on the first true here. + should_accept = true; + } + } + return should_accept; + } + + void Process(const char *filename, const devtools_ijar::u4 attr, + const devtools_ijar::u1 *data, const size_t size) override { + for (auto* processor : processors_) { + if (processor->AcceptPure(filename, attr)) { + processor->Process(filename, attr, data, size); + } + } + } + + private: + const vector<PureZipExtractorProcessor*> processors_; +}; + +// A PureZipExtractorProcessor to extract the InstallKeyFile +class GetInstallKeyFileProcessor : public PureZipExtractorProcessor { public: explicit GetInstallKeyFileProcessor(string *install_base_key) : install_base_key_(install_base_key) {} - virtual bool Accept(const char *filename, const devtools_ijar::u4 attr) { - globals->extracted_binaries.push_back(filename); + bool AcceptPure(const char *filename, + const devtools_ijar::u4 attr) const override { return strcmp(filename, "install_base_key") == 0; } - virtual void Process(const char *filename, const devtools_ijar::u4 attr, - const devtools_ijar::u1 *data, const size_t size) { + bool Accept(const char *filename, const devtools_ijar::u4 attr) override { + return AcceptPure(filename, attr); + } + + void Process(const char *filename, const devtools_ijar::u4 attr, + const devtools_ijar::u1 *data, const size_t size) override { string str(reinterpret_cast<const char *>(data), size); blaze_util::StripWhitespace(&str); if (str.size() != 32) { @@ -277,11 +351,14 @@ class GetInstallKeyFileProcessor : public devtools_ijar::ZipExtractorProcessor { string *install_base_key_; }; -// Returns the install base (the root concatenated with the contents of the file -// 'install_base_key' contained as a ZIP entry in the Blaze binary); as a side -// effect, it also populates the extracted_binaries global variable. -static string GetInstallBase(const string &root, const string &self_path) { - GetInstallKeyFileProcessor processor(&globals->install_md5); +// Populates globals->install_md5 and globals->extracted_binaries by reading the +// ZIP entries in the Blaze binary. +static void ComputeInstallMd5AndNoteAllFiles(const string &self_path) { + NoteAllFilesZipProcessor note_all_files_processor( + &globals->extracted_binaries); + GetInstallKeyFileProcessor install_key_processor(&globals->install_md5); + CompoundZipProcessor processor({¬e_all_files_processor, + &install_key_processor}); std::unique_ptr<devtools_ijar::ZipExtractor> extractor( devtools_ijar::ZipExtractor::Create(self_path.c_str(), &processor)); if (extractor.get() == NULL) { @@ -299,7 +376,6 @@ static string GetInstallBase(const string &root, const string &self_path) { die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "\nFailed to find install_base_key's in zip file"); } - return blaze_util::JoinPath(root, globals->install_md5); } // Escapes colons by replacing them with '_C' and underscores by replacing them @@ -797,19 +873,23 @@ static void StartServerAndConnect(const WorkspaceLayout *workspace_layout, server_pid); } -// A devtools_ijar::ZipExtractorProcessor to extract the files from the blaze -// zip. -class ExtractBlazeZipProcessor : public devtools_ijar::ZipExtractorProcessor { +// A PureZipExtractorProcessor to extract the files from the blaze zip. +class ExtractBlazeZipProcessor : public PureZipExtractorProcessor { public: explicit ExtractBlazeZipProcessor(const string &embedded_binaries) : embedded_binaries_(embedded_binaries) {} - virtual bool Accept(const char *filename, const devtools_ijar::u4 attr) { + bool AcceptPure(const char *filename, + const devtools_ijar::u4 attr) const override { return !devtools_ijar::zipattr_is_dir(attr); } - virtual void Process(const char *filename, const devtools_ijar::u4 attr, - const devtools_ijar::u1 *data, const size_t size) { + bool Accept(const char *filename, const devtools_ijar::u4 attr) override { + return AcceptPure(filename, attr); + } + + void Process(const char *filename, const devtools_ijar::u4 attr, + const devtools_ijar::u1 *data, const size_t size) override { string path = blaze_util::JoinPath(embedded_binaries_, filename); if (!blaze_util::MakeDirectories(blaze_util::Dirname(path), 0777)) { pdie(blaze_exit_code::INTERNAL_ERROR, "couldn't create '%s'", @@ -831,7 +911,11 @@ class ExtractBlazeZipProcessor : public devtools_ijar::ZipExtractorProcessor { // is 'embedded_binaries'. static void ActuallyExtractData(const string &argv0, const string &embedded_binaries) { - ExtractBlazeZipProcessor processor(embedded_binaries); + std::string install_md5; + GetInstallKeyFileProcessor install_key_processor(&install_md5); + ExtractBlazeZipProcessor extract_blaze_processor(embedded_binaries); + CompoundZipProcessor processor({&extract_blaze_processor, + &install_key_processor}); if (!blaze_util::MakeDirectories(embedded_binaries, 0777)) { pdie(blaze_exit_code::INTERNAL_ERROR, "couldn't create '%s'", embedded_binaries.c_str()); @@ -853,6 +937,19 @@ static void ActuallyExtractData(const string &argv0, globals->options->product_name.c_str(), extractor->GetError()); } + if (install_md5 != globals->install_md5) { + die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, + "The %s binary at %s was replaced during the client's self-extraction " + "(old md5: %s new md5: %s). If you expected this then you should " + "simply re-run %s in order to pick up the different version. If you " + "didn't expect this then you should investigate what happened.", + globals->options->product_name.c_str(), + argv0.c_str(), + globals->install_md5.c_str(), + install_md5.c_str(), + globals->options->product_name.c_str()); + } + // Set the timestamps of the extracted files to the future and make sure (or // at least as sure as we can...) that the files we have written are actually // on the disk. @@ -1210,8 +1307,9 @@ static void ComputeWorkspace(const WorkspaceLayout *workspace_layout) { } // Figure out the base directories based on embedded data, username, cwd, etc. -// Sets globals->options->install_base, globals->options->output_base, -// globals->lockfile, globals->jvm_log_file. +// Ensures that all of globals->options->install_base, +// globals->options->output_base, globals->extracted_binaries, +// globals->lockfile, globals->jvm_log_file, and globals->install_md5 are set. static void ComputeBaseDirectories(const WorkspaceLayout *workspace_layout, const string &self_path) { // Only start a server when in a workspace because otherwise we won't do more @@ -1226,12 +1324,13 @@ static void ComputeBaseDirectories(const WorkspaceLayout *workspace_layout, if (globals->options->install_base.empty()) { string install_user_root = blaze_util::JoinPath(globals->options->output_user_root, "install"); - globals->options->install_base = - GetInstallBase(install_user_root, self_path); + ComputeInstallMd5AndNoteAllFiles(self_path); + globals->options->install_base = blaze_util::JoinPath(install_user_root, + globals->install_md5); } else { - // We call GetInstallBase anyway to populate extracted_binaries and - // install_md5. - GetInstallBase("", self_path); + // We still need to populate globals->install_md5 and + // globals->extracted_binaries. + ComputeInstallMd5AndNoteAllFiles(self_path); } if (globals->options->output_base.empty()) { |