Loading tools/signapk/SignApk.java +66 −10 Original line number Diff line number Diff line Loading @@ -461,24 +461,75 @@ class SignApk { * reduce variation in the output file and make incremental OTAs * more efficient. */ private static void copyFiles(Manifest manifest, JarFile in, JarOutputStream out, long timestamp) throws IOException { private static void copyFiles(Manifest manifest, JarFile in, JarOutputStream out, long timestamp, int alignment) throws IOException { byte[] buffer = new byte[4096]; int num; Map<String, Attributes> entries = manifest.getEntries(); ArrayList<String> names = new ArrayList<String>(entries.keySet()); 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) { JarEntry inEntry = in.getJarEntry(name); JarEntry outEntry = null; if (inEntry.getMethod() == JarEntry.STORED) { if (inEntry.getMethod() != JarEntry.STORED) continue; // Preserve the STORED method of the input entry. 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. outEntry = new JarEntry(name); } outEntry.setTime(timestamp); out.putNextEntry(outEntry); Loading Loading @@ -589,7 +640,7 @@ class SignApk { long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000; Manifest manifest = addDigestsToManifest(inputJar, hash); copyFiles(manifest, inputJar, outputJar, timestamp); copyFiles(manifest, inputJar, outputJar, timestamp, 0); addOtacert(outputJar, publicKeyFile, timestamp, manifest, hash); signFile(manifest, inputJar, Loading Loading @@ -778,6 +829,7 @@ class SignApk { private static void usage() { System.err.println("Usage: signapk [-w] " + "[-a <alignment>] " + "[-providerClass <className>] " + "publickey.x509[.pem] privatekey.pk8 " + "[publickey2.x509[.pem] privatekey2.pk8 ...] " + Loading @@ -794,6 +846,7 @@ class SignApk { boolean signWholeFile = false; String providerClass = null; String providerArg = null; int alignment = 4; int argstart = 0; while (argstart < args.length && args[argstart].startsWith("-")) { Loading @@ -806,6 +859,9 @@ class SignApk { } providerClass = args[++argstart]; ++argstart; } else if ("-a".equals(args[argstart])) { alignment = Integer.parseInt(args[++argstart]); ++argstart; } else { usage(); } Loading Loading @@ -872,7 +928,7 @@ class SignApk { outputJar.setLevel(9); Manifest manifest = addDigestsToManifest(inputJar, hashes); copyFiles(manifest, inputJar, outputJar, timestamp); copyFiles(manifest, inputJar, outputJar, timestamp, alignment); signFile(manifest, inputJar, publicKey, privateKey, outputJar); outputJar.close(); } Loading Loading
tools/signapk/SignApk.java +66 −10 Original line number Diff line number Diff line Loading @@ -461,24 +461,75 @@ class SignApk { * reduce variation in the output file and make incremental OTAs * more efficient. */ private static void copyFiles(Manifest manifest, JarFile in, JarOutputStream out, long timestamp) throws IOException { private static void copyFiles(Manifest manifest, JarFile in, JarOutputStream out, long timestamp, int alignment) throws IOException { byte[] buffer = new byte[4096]; int num; Map<String, Attributes> entries = manifest.getEntries(); ArrayList<String> names = new ArrayList<String>(entries.keySet()); 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) { JarEntry inEntry = in.getJarEntry(name); JarEntry outEntry = null; if (inEntry.getMethod() == JarEntry.STORED) { if (inEntry.getMethod() != JarEntry.STORED) continue; // Preserve the STORED method of the input entry. 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. outEntry = new JarEntry(name); } outEntry.setTime(timestamp); out.putNextEntry(outEntry); Loading Loading @@ -589,7 +640,7 @@ class SignApk { long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000; Manifest manifest = addDigestsToManifest(inputJar, hash); copyFiles(manifest, inputJar, outputJar, timestamp); copyFiles(manifest, inputJar, outputJar, timestamp, 0); addOtacert(outputJar, publicKeyFile, timestamp, manifest, hash); signFile(manifest, inputJar, Loading Loading @@ -778,6 +829,7 @@ class SignApk { private static void usage() { System.err.println("Usage: signapk [-w] " + "[-a <alignment>] " + "[-providerClass <className>] " + "publickey.x509[.pem] privatekey.pk8 " + "[publickey2.x509[.pem] privatekey2.pk8 ...] " + Loading @@ -794,6 +846,7 @@ class SignApk { boolean signWholeFile = false; String providerClass = null; String providerArg = null; int alignment = 4; int argstart = 0; while (argstart < args.length && args[argstart].startsWith("-")) { Loading @@ -806,6 +859,9 @@ class SignApk { } providerClass = args[++argstart]; ++argstart; } else if ("-a".equals(args[argstart])) { alignment = Integer.parseInt(args[++argstart]); ++argstart; } else { usage(); } Loading Loading @@ -872,7 +928,7 @@ class SignApk { outputJar.setLevel(9); Manifest manifest = addDigestsToManifest(inputJar, hashes); copyFiles(manifest, inputJar, outputJar, timestamp); copyFiles(manifest, inputJar, outputJar, timestamp, alignment); signFile(manifest, inputJar, publicKey, privateKey, outputJar); outputJar.close(); } Loading