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/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;