aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/singlejar
diff options
context:
space:
mode:
authorGravatar Sasha Smundak <asmundak@google.com>2016-09-23 19:12:31 +0000
committerGravatar Laszlo Csomor <laszlocsomor@google.com>2016-09-26 07:47:02 +0000
commit6673b31f4fb63339e169879e1c37f748020c3abe (patch)
tree0c4a0655074af3b92f0868c8c31da0f96a5386d1 /src/tools/singlejar
parent48859c1daeb931313f7b7e6cae447699b07d997e (diff)
Add '0xCAFE' extra field to the first entry of the output jar (which is META-INF/). Unix 'file' utility uses it to distinguish jar file from zip file.
-- MOS_MIGRATED_REVID=134102453
Diffstat (limited to 'src/tools/singlejar')
-rw-r--r--src/tools/singlejar/output_jar.cc23
-rw-r--r--src/tools/singlejar/output_jar.h4
-rw-r--r--src/tools/singlejar/output_jar_simple_test.cc16
-rw-r--r--src/tools/singlejar/zip_headers.h2
4 files changed, 35 insertions, 10 deletions
diff --git a/src/tools/singlejar/output_jar.cc b/src/tools/singlejar/output_jar.cc
index 855afe6d2c..d5e2c10969 100644
--- a/src/tools/singlejar/output_jar.cc
+++ b/src/tools/singlejar/output_jar.cc
@@ -191,7 +191,7 @@ int OutputJar::Doit(Options *options) {
bool compress = options_->force_compression || options_->preserve_compression;
// First, write a directory entry for the META-INF, followed by the manifest
// file, followed by the build properties file.
- AddDirectory("META-INF/");
+ WriteMetaInf();
manifest_.Append("\r\n");
WriteEntry(manifest_.OutputEntry(compress));
if (!options_->exclude_build_data) {
@@ -538,8 +538,8 @@ void OutputJar::WriteEntry(void *buffer) {
diag_err(1, "%s:%d: write", __FILE__, __LINE__);
}
// Data written, allocate CDH space and populate CDH.
- CDH *cdh = reinterpret_cast<CDH *>(
- ReserveCdh(sizeof(CDH) + entry->file_name_length()));
+ CDH *cdh = reinterpret_cast<CDH *>(ReserveCdh(
+ sizeof(CDH) + entry->file_name_length() + entry->extra_fields_length()));
cdh->signature();
// Note: do not set the version to Unix 3.0 spec, otherwise
// unzip will think that 'external_attributes' field contains access mode
@@ -555,7 +555,7 @@ void OutputJar::WriteEntry(void *buffer) {
TODO(entry->uncompressed_file_size32() != 0xFFFFFFFF, "Handle Zip64");
cdh->uncompressed_file_size32(entry->uncompressed_file_size32());
cdh->file_name(entry->file_name(), entry->file_name_length());
- cdh->extra_fields(nullptr, 0);
+ cdh->extra_fields(entry->extra_fields(), entry->extra_fields_length());
cdh->comment_length(0);
cdh->start_disk_nr(0);
cdh->internal_attributes(0);
@@ -565,9 +565,18 @@ void OutputJar::WriteEntry(void *buffer) {
free(reinterpret_cast<void *>(entry));
}
-void OutputJar::AddDirectory(const char *path) {
+void OutputJar::WriteMetaInf() {
+ const char path[] = "META-INF/";
size_t n_path = strlen(path);
- size_t lh_size = sizeof(LH) + n_path;
+
+ // META_INF/ is always the first entry, and as such it should have an extra
+ // field with the tag 0xCAFE and zero bytes of data. This is not the part of
+ // the jar file spec, but Unix 'file' utility relies on it to distiguish jar
+ // file from zip file. See https://bugs.openjdk.java.net/browse/JDK-6808540
+ const uint8_t extra_fields[] = {0xFE, 0xCA, 0, 0};
+ const uint16_t n_extra_fields =
+ sizeof(extra_fields) / sizeof(extra_fields[0]);
+ size_t lh_size = sizeof(LH) + n_path + n_extra_fields;
LH *lh = reinterpret_cast<LH *>(malloc(lh_size));
lh->signature();
lh->version(20); // 2.0
@@ -577,7 +586,7 @@ void OutputJar::AddDirectory(const char *path) {
lh->compressed_file_size32(0);
lh->uncompressed_file_size32(0);
lh->file_name(path, n_path);
- lh->extra_fields(nullptr, 0);
+ lh->extra_fields(extra_fields, n_extra_fields);
known_members_.emplace(path, EntryInfo{&null_combiner_});
WriteEntry(lh);
}
diff --git a/src/tools/singlejar/output_jar.h b/src/tools/singlejar/output_jar.h
index 082bf7a33b..be3bef8aad 100644
--- a/src/tools/singlejar/output_jar.h
+++ b/src/tools/singlejar/output_jar.h
@@ -71,8 +71,8 @@ class OutputJar {
off_t Position();
// Write Jar entry.
void WriteEntry(void *local_header_and_payload);
- // Write a directory entry.
- void AddDirectory(const char *path);
+ // Write META_INF/ entry (the first entry on output).
+ void WriteMetaInf();
// Append given Central Directory Header to CEN (Central Directory) buffer.
CDH *AppendToDirectoryBuffer(const CDH *cdh);
// Reserve space in CEN buffer.
diff --git a/src/tools/singlejar/output_jar_simple_test.cc b/src/tools/singlejar/output_jar_simple_test.cc
index de9751ba15..6bad8e3fc4 100644
--- a/src/tools/singlejar/output_jar_simple_test.cc
+++ b/src/tools/singlejar/output_jar_simple_test.cc
@@ -115,9 +115,12 @@ TEST_F(OutputJarSimpleTest, Empty) {
CreateOutput(out_path, {});
InputJar input_jar;
ASSERT_TRUE(input_jar.Open(out_path));
+ int entry_count = 0;
const LH *lh;
const CDH *cdh;
+ const uint8_t cafe_extra_field[] = {0xFE, 0xCA, 0, 0};
while ((cdh = input_jar.NextEntry(&lh))) {
+ ++entry_count;
ASSERT_TRUE(cdh->is()) << "No expected tag in the Central Directory Entry.";
ASSERT_NE(nullptr, lh) << "No local header.";
ASSERT_TRUE(lh->is()) << "No expected tag in the Local Header.";
@@ -163,6 +166,19 @@ TEST_F(OutputJarSimpleTest, Empty) {
EXPECT_GE(now, entry_time) << now_time_str << " vs. " << entry_time_str;
EXPECT_LE(now, entry_time + 300) << now_time_str << " vs. "
<< entry_time_str;
+
+ // The first entry should be for the META-INF/ directory, and it should
+ // contain a single extra field 0xCAFE. Although
+ // https://bugs.openjdk.java.net/browse/JDK-6808540 claims that this extra
+ // field is optional, 'file' utility in Linux relies on to distinguish
+ // jar from zip.
+ if (entry_count == 1) {
+ ASSERT_EQ("META-INF/", lh->file_name_string());
+ ASSERT_EQ(4, lh->extra_fields_length());
+ ASSERT_EQ(0, memcmp(cafe_extra_field, lh->extra_fields(), 4));
+ ASSERT_EQ(4, cdh->extra_fields_length());
+ ASSERT_EQ(0, memcmp(cafe_extra_field, cdh->extra_fields(), 4));
+ }
}
input_jar.Close();
string manifest = GetEntryContents(out_path, "META-INF/MANIFEST.MF");
diff --git a/src/tools/singlejar/zip_headers.h b/src/tools/singlejar/zip_headers.h
index 02f8167973..226c7cb800 100644
--- a/src/tools/singlejar/zip_headers.h
+++ b/src/tools/singlejar/zip_headers.h
@@ -243,7 +243,7 @@ class LH {
uint8_t *extra_fields() {
return reinterpret_cast<uint8_t *>(file_name_) + file_name_length();
}
- void extra_fields(uint8_t *data, uint16_t data_length) {
+ void extra_fields(const uint8_t *data, uint16_t data_length) {
extra_fields_length_ = htole16(data_length);
if (data_length) {
memcpy(extra_fields(), data, data_length);