singlejar: add support to for reading in-memory jar data
PiperOrigin-RevId: 627812833
Change-Id: I63915df8897a37d1cbd7da4c73098f9098cc7d77
diff --git a/src/tools/singlejar/input_jar.cc b/src/tools/singlejar/input_jar.cc
index 4b3deb9..ecfbd49 100644
--- a/src/tools/singlejar/input_jar.cc
+++ b/src/tools/singlejar/input_jar.cc
@@ -14,6 +14,11 @@
#include "src/tools/singlejar/input_jar.h"
+#include <cstddef>
+#include <string>
+
+#include "src/tools/singlejar/diag.h"
+
bool InputJar::Open(const std::string &path) {
if (!path_.empty()) {
diag_errx(1, "%s:%d: This instance is already handling %s\n", __FILE__,
@@ -33,7 +38,19 @@
mapped_file_.Close();
return false;
}
+ return LocateCentralDirectory(path);
+}
+bool InputJar::Open(const std::string &path, unsigned char *data,
+ size_t length) {
+ if (path.empty()) {
+ diag_errx(1, "%s:%d: A non-empty path is required\n", __FILE__, __LINE__);
+ }
+ mapped_file_.MapExisting(data, data + length);
+ return LocateCentralDirectory(path);
+}
+
+bool InputJar::LocateCentralDirectory(const std::string &path) {
// Now locate End of Central Directory (ECD) record.
auto ecd_min = mapped_file_.end() - 65536 - sizeof(ECD);
if (ecd_min < mapped_file_.start()) {
diff --git a/src/tools/singlejar/input_jar.h b/src/tools/singlejar/input_jar.h
index 5f7a1fc..e38191e 100644
--- a/src/tools/singlejar/input_jar.h
+++ b/src/tools/singlejar/input_jar.h
@@ -22,6 +22,8 @@
#include <inttypes.h>
#include <stdlib.h>
+#include <cstddef>
+#include <cstdint>
#include <string>
#include "src/tools/singlejar/diag.h"
@@ -51,7 +53,11 @@
#endif
// Opens the file, memory maps it and locates Central Directory.
- bool Open(const std::string& path);
+ bool Open(const std::string &path);
+
+ // Creates an input jar from data that's already in memory.
+ // Requires a non-empty path for use in diagnostics.
+ bool Open(const std::string &path, unsigned char *data, size_t length);
// Returns the next Central Directory Header or nullptr.
const CDH *NextEntry(const LH **local_header_ptr) {
@@ -98,6 +104,8 @@
}
private:
+ bool LocateCentralDirectory(const std::string &path);
+
std::string path_;
MappedFile mapped_file_;
const CDH *cdh_; // current directory entry
diff --git a/src/tools/singlejar/input_jar_scan_entries_test.h b/src/tools/singlejar/input_jar_scan_entries_test.h
index ebb634e..112758e 100644
--- a/src/tools/singlejar/input_jar_scan_entries_test.h
+++ b/src/tools/singlejar/input_jar_scan_entries_test.h
@@ -23,8 +23,8 @@
#include <string>
#include "src/tools/singlejar/input_jar.h"
+#include "src/tools/singlejar/mapped_file.h"
#include "src/tools/singlejar/test_util.h"
-
#include "googletest/include/gtest/gtest.h"
static const char kJar[] = "jar.jar";
@@ -274,7 +274,44 @@
EXPECT_LE(256 * 256, file_count);
}
+TYPED_TEST_P(InputJarScanEntries, BasicInMemory) {
+ ASSERT_EQ(0, chdir(getenv("TEST_TMPDIR")));
+ this->CreateBasicJar();
+ MappedFile mapped_file;
+ ASSERT_TRUE(mapped_file.Open(kJar));
+ ASSERT_TRUE(this->input_jar_->Open(
+ kJar, const_cast<unsigned char *>(mapped_file.start()),
+ mapped_file.size()));
+ const LH *lh;
+ const CDH *cdh;
+ int file_count = 0;
+ bool res1_present = false;
+ bool res2_present = false;
+ while ((cdh = this->input_jar_->NextEntry(&lh))) {
+ this->SmogCheck(cdh, lh);
+ if ('/' != lh->file_name()[lh->file_name_length() - 1]) {
+ ++file_count;
+ if (cdh->file_name_is(kRes1)) {
+ EXPECT_EQ(res1_size, cdh->uncompressed_file_size());
+ res1_present = true;
+ } else if (cdh->file_name_is(kRes2)) {
+ EXPECT_EQ(res2_size, cdh->uncompressed_file_size());
+ res2_present = true;
+ }
+ }
+ }
+
+ this->input_jar_->Close();
+ mapped_file.Close();
+ unlink(kJar);
+ EXPECT_TRUE(res1_present)
+ << "Jar file " << kJar << " lacks expected '" << kRes1 << "' file.";
+ EXPECT_TRUE(res2_present)
+ << "Jar file " << kJar << " lacks expected '" << kRes2 << "' file.";
+}
+
REGISTER_TYPED_TEST_SUITE_P(InputJarScanEntries, OpenClose, Basic,
- HugeUncompressed, TestZip64, LotsOfEntries);
+ HugeUncompressed, TestZip64, LotsOfEntries,
+ BasicInMemory);
#endif // BAZEL_SRC_TOOLS_SINGLEJAR_INPUT_JAR_SCAN_ENTRIES_TEST_H_
diff --git a/src/tools/singlejar/mapped_file.h b/src/tools/singlejar/mapped_file.h
index 163eeee..4e1790d 100644
--- a/src/tools/singlejar/mapped_file.h
+++ b/src/tools/singlejar/mapped_file.h
@@ -15,6 +15,7 @@
#ifndef BAZEL_SRC_TOOLS_SINGLEJAR_MAPPED_FILE_H_
#define BAZEL_SRC_TOOLS_SINGLEJAR_MAPPED_FILE_H_ 1
+#include <cstddef>
#include <string>
#include "src/tools/singlejar/port.h"
@@ -36,6 +37,12 @@
bool Open(const std::string &path);
+ bool MapExisting(unsigned char *mapped_start, unsigned char *mapped_end) {
+ mapped_start_ = mapped_start;
+ mapped_end_ = mapped_end;
+ return true;
+ }
+
void Close();
bool mapped(const void *addr) const {
@@ -60,9 +67,10 @@
#endif
size_t size() const { return mapped_end_ - mapped_start_; }
- bool is_open() const;
private:
+ bool is_open() const;
+
unsigned char *mapped_start_;
unsigned char *mapped_end_;
#ifdef _WIN32