aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/ijar
diff options
context:
space:
mode:
authorGravatar cushon <cushon@google.com>2018-03-21 20:30:12 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-03-21 20:32:06 -0700
commitf572845d04c579e81b2dc78e8efeea12dc7dbee7 (patch)
tree068525bf67cfaec5ed1c4d384b9de7dd0c0b0da5 /third_party/ijar
parent2410e1ab3e035382abe519003c618271a69a7b8e (diff)
Include manifest size when presizing ijar output
PiperOrigin-RevId: 190010996
Diffstat (limited to 'third_party/ijar')
-rw-r--r--third_party/ijar/ijar.cc46
-rw-r--r--third_party/ijar/mapped_file.h1
-rw-r--r--third_party/ijar/mapped_file_unix.cc9
-rw-r--r--third_party/ijar/test/BUILD10
-rw-r--r--third_party/ijar/test/IjarTests.java12
5 files changed, 72 insertions, 6 deletions
diff --git a/third_party/ijar/ijar.cc b/third_party/ijar/ijar.cc
index d7742ee1ac..2ed559dad2 100644
--- a/third_party/ijar/ijar.cc
+++ b/third_party/ijar/ijar.cc
@@ -36,13 +36,20 @@ bool StripClass(u1*& classdata_out, const u1* classdata_in, size_t in_length);
const char* CLASS_EXTENSION = ".class";
const size_t CLASS_EXTENSION_LENGTH = strlen(CLASS_EXTENSION);
+const char *MANIFEST_DIR_PATH = "META-INF/";
+const size_t MANIFEST_DIR_PATH_LENGTH = strlen(MANIFEST_DIR_PATH);
+const char *MANIFEST_PATH = "META-INF/MANIFEST.MF";
+const size_t MANIFEST_PATH_LENGTH = strlen(MANIFEST_PATH);
const char *MANIFEST_HEADER =
- "Manifest-Version: 1.0\n"
- "Created-By: bazel\n";
+ "Manifest-Version: 1.0\r\n"
+ "Created-By: bazel\r\n";
+const size_t MANIFEST_HEADER_LENGTH = strlen(MANIFEST_HEADER);
// These attributes are used by JavaBuilder, Turbine, and ijar.
// They must all be kept in sync.
const char *TARGET_LABEL_KEY = "Target-Label: ";
+const size_t TARGET_LABEL_KEY_LENGTH = strlen(TARGET_LABEL_KEY);
const char *INJECTING_RULE_KIND_KEY = "Injecting-Rule-Kind: ";
+const size_t INJECTING_RULE_KIND_KEY_LENGTH = strlen(INJECTING_RULE_KIND_KEY);
// ZipExtractorProcessor that select only .class file and use
// StripClass to generate an interface class, storing as a new file
@@ -120,21 +127,48 @@ static size_t WriteStr(u1 *buf, const char *str) {
return len;
}
+// Computes the size of zip file content for the manifest created by
+// WriteManifest, including zip file format overhead.
+static size_t EstimateManifestOutputSize(const char *target_label,
+ const char *injecting_rule_kind) {
+ if (target_label == NULL) {
+ return 0;
+ }
+ // local headers
+ size_t length = 30 * 2 + MANIFEST_DIR_PATH_LENGTH + MANIFEST_PATH_LENGTH;
+ // central directory
+ length += 46 * 2 + MANIFEST_DIR_PATH_LENGTH + MANIFEST_PATH_LENGTH;
+ // zip64 EOCD entries
+ length += 56 * 2;
+
+ // manifest content
+ length += MANIFEST_HEADER_LENGTH;
+ // target label manifest entry, including newline
+ length += TARGET_LABEL_KEY_LENGTH + strlen(target_label) + 2;
+ if (injecting_rule_kind) {
+ // injecting rule kind manifest entry, including newline
+ length += INJECTING_RULE_KIND_KEY_LENGTH + strlen(injecting_rule_kind) + 2;
+ }
+ return length;
+}
+
static void WriteManifest(ZipBuilder *out, const char *target_label,
const char *injecting_rule_kind) {
if (target_label == NULL) {
return;
}
- out->WriteEmptyFile("META-INF/");
- u1 *start = out->NewFile("META-INF/MANIFEST.MF", 0);
+ out->WriteEmptyFile(MANIFEST_DIR_PATH);
+ u1 *start = out->NewFile(MANIFEST_PATH, 0);
u1 *buf = start;
buf += WriteStr(buf, MANIFEST_HEADER);
buf += WriteStr(buf, TARGET_LABEL_KEY);
buf += WriteStr(buf, target_label);
+ *buf++ = '\r';
*buf++ = '\n';
if (injecting_rule_kind) {
buf += WriteStr(buf, INJECTING_RULE_KIND_KEY);
buf += WriteStr(buf, injecting_rule_kind);
+ *buf++ = '\r';
*buf++ = '\n';
}
size_t total_len = buf - start;
@@ -153,7 +187,9 @@ static void OpenFilesAndProcessJar(const char *file_out, const char *file_in,
strerror(errno));
abort();
}
- u8 output_length = in->CalculateOutputLength();
+ u8 output_length =
+ in->CalculateOutputLength() +
+ EstimateManifestOutputSize(target_label, injecting_rule_kind);
std::unique_ptr<ZipBuilder> out(ZipBuilder::Create(file_out, output_length));
if (out.get() == NULL) {
fprintf(stderr, "Unable to open output file %s: %s\n", file_out,
diff --git a/third_party/ijar/mapped_file.h b/third_party/ijar/mapped_file.h
index 6db0673bae..7653638d5f 100644
--- a/third_party/ijar/mapped_file.h
+++ b/third_party/ijar/mapped_file.h
@@ -62,6 +62,7 @@ class MappedOutputFile {
const char* errmsg_;
bool opened_;
u1* buffer_;
+ u8 estimated_size_;
public:
MappedOutputFile(const char* name, u8 estimated_size);
diff --git a/third_party/ijar/mapped_file_unix.cc b/third_party/ijar/mapped_file_unix.cc
index d5a0b57cac..ccb8787cd5 100644
--- a/third_party/ijar/mapped_file_unix.cc
+++ b/third_party/ijar/mapped_file_unix.cc
@@ -90,7 +90,8 @@ struct MappedOutputFileImpl {
int mmap_length_;
};
-MappedOutputFile::MappedOutputFile(const char* name, u8 estimated_size) {
+MappedOutputFile::MappedOutputFile(const char* name, u8 estimated_size)
+ : estimated_size_(estimated_size) {
impl_ = NULL;
opened_ = false;
int fd = open(name, O_CREAT|O_RDWR|O_TRUNC, 0644);
@@ -131,6 +132,12 @@ MappedOutputFile::~MappedOutputFile() {
}
int MappedOutputFile::Close(int size) {
+ if (size > estimated_size_) {
+ snprintf(errmsg, MAX_ERROR, "size %d > estimated size %lld", size,
+ estimated_size_);
+ errmsg_ = errmsg;
+ return -1;
+ }
munmap(buffer_, impl_->mmap_length_);
if (ftruncate(impl_->fd_, size) < 0) {
snprintf(errmsg, MAX_ERROR, "ftruncate(): %s", strerror(errno));
diff --git a/third_party/ijar/test/BUILD b/third_party/ijar/test/BUILD
index d9ab5f788e..62b6edd3a3 100644
--- a/third_party/ijar/test/BUILD
+++ b/third_party/ijar/test/BUILD
@@ -109,6 +109,14 @@ genrule(
tools = ["//third_party/ijar"],
)
+genrule(
+ name = "empty_with_target_label",
+ srcs = [":empty_zip.jar"],
+ outs = ["empty_with_target_label.jar"],
+ cmd = "$(location //third_party/ijar) $< $@ --target_label //empty",
+ tools = ["//third_party/ijar"],
+)
+
java_library(
name = "typeannotations2",
srcs = glob(["typeannotations2/**/*.java"]),
@@ -187,6 +195,7 @@ java_test(
"UseDeprecatedParts.java",
"UseRestrictedAnnotation.java",
"package-info.java",
+ ":empty_with_target_label",
":interface_ijar_testlib",
":interface_ijar_testlib_with_target_label",
":liblocal_and_anonymous_lib.jar",
@@ -234,6 +243,7 @@ java_binary(
("largest_regular", 65535),
("smallest_zip64", 65536),
("definitely_zip64", 70000),
+ ("empty_zip", 1),
]
]
diff --git a/third_party/ijar/test/IjarTests.java b/third_party/ijar/test/IjarTests.java
index a2e10db570..dc6c02062a 100644
--- a/third_party/ijar/test/IjarTests.java
+++ b/third_party/ijar/test/IjarTests.java
@@ -292,4 +292,16 @@ public class IjarTests {
LocalDateTime.of(2010, 1, 1, 0, 0, 0).atZone(ZoneOffset.systemDefault()).toInstant());
}
}
+
+ @Test
+ public void testEmptyWithTargetLabel() throws Exception {
+ try (JarFile jf = new JarFile("third_party/ijar/test/empty_with_target_label.jar")) {
+ Manifest manifest = jf.getManifest();
+ Attributes attributes = manifest.getMainAttributes();
+ assertThat(attributes.getValue("Target-Label")).isEqualTo("//empty");
+ assertThat(jf.getEntry(JarFile.MANIFEST_NAME).getLastModifiedTime().toInstant())
+ .isEqualTo(
+ LocalDateTime.of(2010, 1, 1, 0, 0, 0).atZone(ZoneOffset.systemDefault()).toInstant());
+ }
+ }
}