Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7933482 authored by Doug Zongker's avatar Doug Zongker Committed by Android Git Automerger
Browse files

am c0f10644: Merge "make SignApk do zip alignment"

* commit 'c0f10644':
  make SignApk do zip alignment
parents 658d89e9 c0f10644
Loading
Loading
Loading
Loading
+66 −10
Original line number Diff line number Diff line
@@ -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);

@@ -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,
@@ -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 ...] " +
@@ -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("-")) {
@@ -806,6 +859,9 @@ class SignApk {
                }
                providerClass = args[++argstart];
                ++argstart;
            } else if ("-a".equals(args[argstart])) {
                alignment = Integer.parseInt(args[++argstart]);
                ++argstart;
            } else {
                usage();
            }
@@ -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();
            }