Use the ijar ZIP implementation in Blaze instead of libarchive This ZIP implementation is lightweight and rely on zlib for compression. libarchive was a bit tricky to set-up so it's better to use that one. -- Change-Id: I607b492998572e834e095a4606eeb77c0b574542 Reviewed-on: https://bazel-review.googlesource.com/#/c/1410/ MOS_MIGRATED_REVID=94910072
diff --git a/src/main/cpp/BUILD b/src/main/cpp/BUILD index a4aeec9..f2f4579 100644 --- a/src/main/cpp/BUILD +++ b/src/main/cpp/BUILD
@@ -57,20 +57,13 @@ "//src:darwin": [ ], "//conditions:default": [ - "-larchive", "-lrt", ], }), visibility = ["//src:__pkg__"], - deps = select({ - "//src:darwin": [ - ":md5", - ":util", - "//fromhost:libarchive", - ], - "//conditions:default": [ - ":md5", - ":util", - ], - }), + deps = [ + ":md5", + ":util", + "//third_party/ijar:zip", + ], )
diff --git a/src/main/cpp/blaze.cc b/src/main/cpp/blaze.cc index 42dcda0..0f009e6 100644 --- a/src/main/cpp/blaze.cc +++ b/src/main/cpp/blaze.cc
@@ -65,8 +65,7 @@ #include "src/main/cpp/util/numbers.h" #include "src/main/cpp/util/port.h" #include "src/main/cpp/util/strings.h" -#include "archive.h" -#include "archive_entry.h" +#include "third_party/ijar/zip.h" using blaze_util::Md5Digest; using blaze_util::die; @@ -169,49 +168,54 @@ return root + "/" + digest.String(); } +// A devtools_ijar::ZipExtractorProcessor to extract the InstallKeyFile +class GetInstallKeyFileProcessor : public devtools_ijar::ZipExtractorProcessor { + public: + 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); + 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) { + string str(reinterpret_cast<const char *>(data), size); + blaze_util::StripWhitespace(&str); + if (str.size() < 32) { + die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, + "\nFailed to extract install_base_key: file too short"); + } + *install_base_key_ = str; + } + + private: + 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) { - string key_file = "install_base_key"; - struct archive *blaze_zip = archive_read_new(); - archive_read_support_format_zip(blaze_zip); - int retval = archive_read_open_filename(blaze_zip, self_path.c_str(), 10240); - if (retval != ARCHIVE_OK) { + string install_base_key; + GetInstallKeyFileProcessor processor(&install_base_key); + std::unique_ptr<devtools_ijar::ZipExtractor> extractor( + devtools_ijar::ZipExtractor::Create(self_path.c_str(), &processor)); + if (extractor.get() == NULL) { die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "\nFailed to open %s as a zip file: (%d) %s", - globals->options.GetProductName().c_str(), archive_errno(blaze_zip), - archive_error_string(blaze_zip)); + globals->options.GetProductName().c_str(), errno, strerror(errno)); } - - struct archive_entry *entry; - string install_base_key; - while (archive_read_next_header(blaze_zip, &entry) == ARCHIVE_OK) { - string pathname = archive_entry_pathname(entry); - globals->extracted_binaries.push_back(pathname); - - if (key_file == pathname) { - const int size = 32; - char buf[size]; - int bytesRead = archive_read_data(blaze_zip, &buf, size); - if (bytesRead < 0) { - die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, - "\nFailed to extract install_base_key: (%d) %s", - archive_errno(blaze_zip), archive_error_string(blaze_zip)); - } - if (bytesRead < 32) { - die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, - "\nFailed to extract install_base_key: file too short"); - } - install_base_key = string(buf, bytesRead); - } - } - retval = archive_read_free(blaze_zip); - if (retval != ARCHIVE_OK) { + if (extractor->ProcessAll() < 0) { die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, - "\nFailed to close install_base_key's containing zip file"); + "\nFailed to extract install_base_key: %s", extractor->GetError()); } + if (install_base_key.empty()) { + die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, + "\nFailed to find install_base_key's in zip file"); + } return root + "/" + install_base_key; } @@ -762,32 +766,20 @@ closedir(dir); } -// Actually extracts the embedded data files into the tree whose root -// is 'embedded_binaries'. -static void ActuallyExtractData(const string &argv0, - const string &embedded_binaries) { - if (MakeDirectories(embedded_binaries, 0777) == -1) { - pdie(blaze_exit_code::INTERNAL_ERROR, - "couldn't create '%s'", embedded_binaries.c_str()); +// A devtools_ijar::ZipExtractorProcessor to extract the files from the blaze +// zip. +class ExtractBlazeZipProcessor : public devtools_ijar::ZipExtractorProcessor { + public: + ExtractBlazeZipProcessor(const string &embedded_binaries) + : embedded_binaries_(embedded_binaries) {} + + virtual bool Accept(const char *filename, const devtools_ijar::u4 attr) { + return !devtools_ijar::zipattr_is_dir(attr); } - fprintf(stderr, "Extracting %s installation...\n", - globals->options.GetProductName().c_str()); - - struct archive *blaze_zip = archive_read_new(); - archive_read_support_format_zip(blaze_zip); - int retval = archive_read_open_filename(blaze_zip, argv0.c_str(), 10240); - if (retval != ARCHIVE_OK) { - die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, - "\nFailed to open %s as a zip file", - globals->options.GetProductName().c_str()); - } - - struct archive_entry *entry; - string install_base_key; - while (archive_read_next_header(blaze_zip, &entry) == ARCHIVE_OK) { - string path = blaze_util::JoinPath( - embedded_binaries, archive_entry_pathname(entry)); + virtual void Process(const char *filename, const devtools_ijar::u4 attr, + const devtools_ijar::u1 *data, const size_t size) { + string path = blaze_util::JoinPath(embedded_binaries_, filename); if (MakeDirectories(blaze_util::Dirname(path), 0777) == -1) { pdie(blaze_exit_code::INTERNAL_ERROR, "couldn't create '%s'", path.c_str()); @@ -798,33 +790,43 @@ "\nFailed to open extraction file: %s", strerror(errno)); } - const void *buf; - size_t size; - int64_t offset; - while (true) { - retval = archive_read_data_block(blaze_zip, &buf, &size, &offset); - if (retval == ARCHIVE_EOF) { - break; - } else if (retval != ARCHIVE_OK) { - die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, - "\nFailed to extract data from %s zip: (%d) %s", - globals->options.GetProductName().c_str(), archive_errno(blaze_zip), - archive_error_string(blaze_zip)); - } - if (write(fd, buf, size) != size) { - die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, - "\nError writing zipped file to %s", path.c_str()); - } + if (write(fd, data, size) != size) { + die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, + "\nError writing zipped file to %s", path.c_str()); } if (close(fd) != 0) { die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "\nCould not close file %s", path.c_str()); } } - retval = archive_read_free(blaze_zip); - if (retval != ARCHIVE_OK) { + + private: + const string embedded_binaries_; +}; + +// Actually extracts the embedded data files into the tree whose root +// is 'embedded_binaries'. +static void ActuallyExtractData(const string &argv0, + const string &embedded_binaries) { + ExtractBlazeZipProcessor processor(embedded_binaries); + if (MakeDirectories(embedded_binaries, 0777) == -1) { + pdie(blaze_exit_code::INTERNAL_ERROR, "couldn't create '%s'", + embedded_binaries.c_str()); + } + + fprintf(stderr, "Extracting %s installation...\n", + globals->options.GetProductName().c_str()); + std::unique_ptr<devtools_ijar::ZipExtractor> extractor( + devtools_ijar::ZipExtractor::Create(argv0.c_str(), &processor)); + if (extractor.get() == NULL) { die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, - "\nFailed to close %s zip", globals->options.GetProductName().c_str()); + "\nFailed to open %s as a zip file: (%d) %s", + globals->options.GetProductName().c_str(), errno, strerror(errno)); + } + if (extractor->ProcessAll() < 0) { + die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, + "\nFailed to extract %s as a zip file: %s", + globals->options.GetProductName().c_str(), extractor->GetError()); } const time_t TEN_YEARS_IN_SEC = 3600 * 24 * 365 * 10;