diff options
author | cushon <cushon@google.com> | 2018-03-21 20:30:12 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-03-21 20:32:06 -0700 |
commit | f572845d04c579e81b2dc78e8efeea12dc7dbee7 (patch) | |
tree | 068525bf67cfaec5ed1c4d384b9de7dd0c0b0da5 /third_party/ijar | |
parent | 2410e1ab3e035382abe519003c618271a69a7b8e (diff) |
Include manifest size when presizing ijar output
PiperOrigin-RevId: 190010996
Diffstat (limited to 'third_party/ijar')
-rw-r--r-- | third_party/ijar/ijar.cc | 46 | ||||
-rw-r--r-- | third_party/ijar/mapped_file.h | 1 | ||||
-rw-r--r-- | third_party/ijar/mapped_file_unix.cc | 9 | ||||
-rw-r--r-- | third_party/ijar/test/BUILD | 10 | ||||
-rw-r--r-- | third_party/ijar/test/IjarTests.java | 12 |
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()); + } + } } |