Merge "make SignApk do zip alignment"
This commit is contained in:
commit
c0f10644bf
|
@ -461,24 +461,75 @@ class SignApk {
|
||||||
* reduce variation in the output file and make incremental OTAs
|
* reduce variation in the output file and make incremental OTAs
|
||||||
* more efficient.
|
* more efficient.
|
||||||
*/
|
*/
|
||||||
private static void copyFiles(Manifest manifest,
|
private static void copyFiles(Manifest manifest, JarFile in, JarOutputStream out,
|
||||||
JarFile in, JarOutputStream out, long timestamp) throws IOException {
|
long timestamp, int alignment) throws IOException {
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
Map<String, Attributes> entries = manifest.getEntries();
|
Map<String, Attributes> entries = manifest.getEntries();
|
||||||
ArrayList<String> names = new ArrayList<String>(entries.keySet());
|
ArrayList<String> names = new ArrayList<String>(entries.keySet());
|
||||||
Collections.sort(names);
|
Collections.sort(names);
|
||||||
|
|
||||||
|
boolean firstEntry = true;
|
||||||
|
long offset = 0L;
|
||||||
|
|
||||||
|
// We do the copy in two passes -- first copying all the
|
||||||
|
// entries that are STORED, then copying all the entries that
|
||||||
|
// have any other compression flag (which in practice means
|
||||||
|
// DEFLATED). This groups all the stored entries together at
|
||||||
|
// the start of the file and makes it easier to do alignment
|
||||||
|
// on them (since only stored entries are aligned).
|
||||||
|
|
||||||
for (String name : names) {
|
for (String name : names) {
|
||||||
JarEntry inEntry = in.getJarEntry(name);
|
JarEntry inEntry = in.getJarEntry(name);
|
||||||
JarEntry outEntry = null;
|
JarEntry outEntry = null;
|
||||||
if (inEntry.getMethod() == JarEntry.STORED) {
|
if (inEntry.getMethod() != JarEntry.STORED) continue;
|
||||||
// Preserve the STORED method of the input entry.
|
// Preserve the STORED method of the input entry.
|
||||||
outEntry = new JarEntry(inEntry);
|
outEntry = new JarEntry(inEntry);
|
||||||
} else {
|
outEntry.setTime(timestamp);
|
||||||
|
|
||||||
|
// 'offset' is the offset into the file at which we expect
|
||||||
|
// the file data to begin. This is the value we need to
|
||||||
|
// make a multiple of 'alignement'.
|
||||||
|
offset += JarFile.LOCHDR + outEntry.getName().length();
|
||||||
|
if (firstEntry) {
|
||||||
|
// The first entry in a jar file has an extra field of
|
||||||
|
// four bytes that you can't get rid of; any extra
|
||||||
|
// data you specify in the JarEntry is appended to
|
||||||
|
// these forced four bytes. This is JAR_MAGIC in
|
||||||
|
// JarOutputStream; the bytes are 0xfeca0000.
|
||||||
|
offset += 4;
|
||||||
|
firstEntry = false;
|
||||||
|
}
|
||||||
|
if (alignment > 0 && (offset % alignment != 0)) {
|
||||||
|
// Set the "extra data" of the entry to between 1 and
|
||||||
|
// alignment-1 bytes, to make the file data begin at
|
||||||
|
// an aligned offset.
|
||||||
|
int needed = alignment - (int)(offset % alignment);
|
||||||
|
outEntry.setExtra(new byte[needed]);
|
||||||
|
offset += needed;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.putNextEntry(outEntry);
|
||||||
|
|
||||||
|
InputStream data = in.getInputStream(inEntry);
|
||||||
|
while ((num = data.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, num);
|
||||||
|
offset += num;
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all the non-STORED entries. We don't attempt to
|
||||||
|
// maintain the 'offset' variable past this point; we don't do
|
||||||
|
// alignment on these entries.
|
||||||
|
|
||||||
|
for (String name : names) {
|
||||||
|
JarEntry inEntry = in.getJarEntry(name);
|
||||||
|
JarEntry outEntry = null;
|
||||||
|
if (inEntry.getMethod() == JarEntry.STORED) continue;
|
||||||
// Create a new entry so that the compressed len is recomputed.
|
// Create a new entry so that the compressed len is recomputed.
|
||||||
outEntry = new JarEntry(name);
|
outEntry = new JarEntry(name);
|
||||||
}
|
|
||||||
outEntry.setTime(timestamp);
|
outEntry.setTime(timestamp);
|
||||||
out.putNextEntry(outEntry);
|
out.putNextEntry(outEntry);
|
||||||
|
|
||||||
|
@ -589,7 +640,7 @@ class SignApk {
|
||||||
long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
|
long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
|
||||||
|
|
||||||
Manifest manifest = addDigestsToManifest(inputJar, hash);
|
Manifest manifest = addDigestsToManifest(inputJar, hash);
|
||||||
copyFiles(manifest, inputJar, outputJar, timestamp);
|
copyFiles(manifest, inputJar, outputJar, timestamp, 0);
|
||||||
addOtacert(outputJar, publicKeyFile, timestamp, manifest, hash);
|
addOtacert(outputJar, publicKeyFile, timestamp, manifest, hash);
|
||||||
|
|
||||||
signFile(manifest, inputJar,
|
signFile(manifest, inputJar,
|
||||||
|
@ -778,6 +829,7 @@ class SignApk {
|
||||||
|
|
||||||
private static void usage() {
|
private static void usage() {
|
||||||
System.err.println("Usage: signapk [-w] " +
|
System.err.println("Usage: signapk [-w] " +
|
||||||
|
"[-a <alignment>] " +
|
||||||
"[-providerClass <className>] " +
|
"[-providerClass <className>] " +
|
||||||
"publickey.x509[.pem] privatekey.pk8 " +
|
"publickey.x509[.pem] privatekey.pk8 " +
|
||||||
"[publickey2.x509[.pem] privatekey2.pk8 ...] " +
|
"[publickey2.x509[.pem] privatekey2.pk8 ...] " +
|
||||||
|
@ -794,6 +846,7 @@ class SignApk {
|
||||||
boolean signWholeFile = false;
|
boolean signWholeFile = false;
|
||||||
String providerClass = null;
|
String providerClass = null;
|
||||||
String providerArg = null;
|
String providerArg = null;
|
||||||
|
int alignment = 4;
|
||||||
|
|
||||||
int argstart = 0;
|
int argstart = 0;
|
||||||
while (argstart < args.length && args[argstart].startsWith("-")) {
|
while (argstart < args.length && args[argstart].startsWith("-")) {
|
||||||
|
@ -806,6 +859,9 @@ class SignApk {
|
||||||
}
|
}
|
||||||
providerClass = args[++argstart];
|
providerClass = args[++argstart];
|
||||||
++argstart;
|
++argstart;
|
||||||
|
} else if ("-a".equals(args[argstart])) {
|
||||||
|
alignment = Integer.parseInt(args[++argstart]);
|
||||||
|
++argstart;
|
||||||
} else {
|
} else {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
@ -872,7 +928,7 @@ class SignApk {
|
||||||
outputJar.setLevel(9);
|
outputJar.setLevel(9);
|
||||||
|
|
||||||
Manifest manifest = addDigestsToManifest(inputJar, hashes);
|
Manifest manifest = addDigestsToManifest(inputJar, hashes);
|
||||||
copyFiles(manifest, inputJar, outputJar, timestamp);
|
copyFiles(manifest, inputJar, outputJar, timestamp, alignment);
|
||||||
signFile(manifest, inputJar, publicKey, privateKey, outputJar);
|
signFile(manifest, inputJar, publicKey, privateKey, outputJar);
|
||||||
outputJar.close();
|
outputJar.close();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue