Commit d5087858 authored by topjohnwu's avatar topjohnwu

Add build scripts

Building through the build script will compile all binaries, and generate a properly signed zip
Should work on linux and macOS environments
parent d9fc5650
obj obj/
libs libs/
*.zip *.zip
# Generated binaries
zip_static/arm/*
zip_static/arm64/*
zip_static/x86/*
zip_static/x64/*
uninstaller/arm/*
uninstaller/arm64/*
uninstaller/x86/*
uninstaller/x64/*
zipsigntools/zipadjust
# Generated scripts
zip_static/common/magic_mask.sh
zip_static/META-INF/com/google/android/update-binary
# Leave all busybox!
!busybox
\ No newline at end of file
#!/bin/bash
usage() {
echo "$0 --all <version number>"
echo -e "\tBuild binaries, zip, and sign Magisk"
echo -e "\tThis is equlivant to first --build, then --zip"
echo "$0 --clean"
echo -e "\tCleanup compiled / generated files"
echo "$0 --build"
echo -e "\tBuild the binaries with ndk"
echo "$0 --zip <version number>"
echo -e "\tZip and sign Magisk"
echo "$0 --uninstaller"
echo -e "\tZip and sign the uninstaller"
exit 1
}
cleanup() {
echo "************************"
echo "* Cleaning up"
echo "************************"
ndk-build clean
ls zip_static/arm/* | grep -v "busybox" | xargs rm -rfv
ls zip_static/arm64/* | grep -v "busybox" | xargs rm -rfv
ls zip_static/x86/* | grep -v "busybox" | xargs rm -rfv
ls zip_static/x64/* | grep -v "busybox" | xargs rm -rfv
rm -rfv zip_static/META-INF/com/google/android/update-binary
rm -rfv zip_static/common/magic_mask.sh
rm -rfv uninstaller/arm
rm -rfv uninstaller/arm64
rm -rfv uninstaller/x86
rm -rfv uninstaller/x64
}
mkcp() {
[ ! -d "$2" ] && mkdir -p "$2"
cp -afv $1 $2
}
build_bin() {
echo "************************"
echo "* Building binaries"
echo "************************"
ndk-build -j4
echo "************************"
echo "* Copying binaries"
echo "************************"
mkcp "libs/armeabi/*" zip_static/arm
mkcp libs/armeabi/bootimgtools uninstaller/arm
mkcp "libs/arm64-v8a/*" zip_static/arm64
mkcp libs/arm64-v8a/bootimgtools uninstaller/arm64
mkcp "libs/x86/*" zip_static/x86
mkcp libs/x86/bootimgtools uninstaller/x86
mkcp "libs/x86_64/*" zip_static/x64
mkcp libs/x86_64/bootimgtools uninstaller/x64
}
zip_package() {
echo "************************"
echo "* Adding version info"
echo "* \"Magisk v$1\""
echo "************************"
sed "s/MAGISK_VERSION_STUB/Magisk v$1 Boot Image Patcher/g" scripts/flash_script.sh > zip_static/META-INF/com/google/android/update-binary
sed "s/MAGISK_VERSION_STUB/setprop magisk.version $1/g" scripts/magic_mask.sh > zip_static/common/magic_mask.sh
echo "************************"
echo "* Zipping the package"
echo "************************"
cd zip_static
find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;
rm -rf "../Magisk-v$1.zip"
zip "../Magisk-v$1.zip" -r .
cd ../
sign_zip "Magisk-v$1.zip"
}
sign_zip() {
if [ ! -f "zipsigntools/zipadjust" ]; then
echo "************************"
echo "* Compiling ZipAdjust"
echo "************************"
gcc -o zipsigntools/zipadjust zipsigntools/src/*.c -lz
chmod 755 zipsigntools/zipadjust
fi
echo "************************"
echo "* First sign $1"
echo "************************"
java -jar "zipsigntools/signapk.jar" "zipsigntools/test.certificate.x509.pem" "zipsigntools/test.key.pk8" "$1" "${1%.*}-firstsign.zip"
echo "************************"
echo "* Adjusting $1"
echo "************************"
zipsigntools/zipadjust "${1%.*}-firstsign.zip" "${1%.*}-adjusted.zip"
echo "************************"
echo "* Final sign $1"
echo "************************"
java -jar "zipsigntools/signapk.jar" "zipsigntools/test.certificate.x509.pem" "zipsigntools/test.key.pk8" "${1%.*}-adjusted.zip" "${1%.*}-signed.zip"
mv "${1%.*}-signed.zip" "$1"
rm "${1%.*}-adjusted.zip" "${1%.*}-firstsign.zip"
}
DIR="$(cd "$(dirname "$0")"; pwd)"
cd "$DIR"
case $1 in
"--all" )
[ -z "$2" ] && echo -e "! Missing version number\n" && usage
build_bin
zip_package $2
;;
"--clean" )
cleanup
;;
"--build" )
build_bin
;;
"--zip" )
[ -z "$2" ] && echo -e "! Missing version number\n" && usage
zip_package $2
;;
"--uninstaller" )
zip_uninstaller
;;
* )
usage
;;
esac
...@@ -184,9 +184,9 @@ repack_boot() { ...@@ -184,9 +184,9 @@ repack_boot() {
# Detection # Detection
########################################################################################## ##########################################################################################
ui_print "****************************" ui_print "*****************************"
ui_print "Magisk v8 Boot Image Patcher" ui_print "MAGISK_VERSION_STUB"
ui_print "****************************" ui_print "*****************************"
if [ ! -d "$INSTALLER/common" ]; then if [ ! -d "$INSTALLER/common" ]; then
ui_print "! Failed: Unable to extract zip file!" ui_print "! Failed: Unable to extract zip file!"
......
...@@ -396,7 +396,7 @@ case $1 in ...@@ -396,7 +396,7 @@ case $1 in
service ) service )
# Version info # Version info
setprop magisk.version 8 MAGISK_VERSION_STUB
log_print "Magisk late_start service mode running..." log_print "Magisk late_start service mode running..."
run_scripts service run_scripts service
[ -f "$COREDIR/magiskhide/enable" ] && setprop magisk.hide 1 [ -f "$COREDIR/magiskhide/enable" ] && setprop magisk.hide 1
......
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This is just a copy/paste/cut job from original SignAPK sources. This
* adaptation adds only the whole-file signature to a ZIP(jar,apk) file, and
* doesn't do any of the per-file signing, creating manifests, etc. This is
* useful when you've changed the structure itself of an existing (signed!)
* ZIP file, but the extracted contents are still identical. Using
* the normal SignAPK may re-arrange other things inside the ZIP, which may
* be unwanted behavior. This version only changes the ZIP's tail and keeps
* the rest the same - CF
*/
package eu.chainfire.minsignapk;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
public class MinSignAPK {
/** Write a .RSA file with a digital signature. */
private static void writeSignatureBlock(Signature signature, X509Certificate publicKey, OutputStream out)
throws IOException, GeneralSecurityException {
SignerInfo signerInfo = new SignerInfo(new X500Name(publicKey.getIssuerX500Principal().getName()),
publicKey.getSerialNumber(), AlgorithmId.get("SHA1"), AlgorithmId.get("RSA"), signature.sign());
PKCS7 pkcs7 = new PKCS7(new AlgorithmId[] { AlgorithmId.get("SHA1") }, new ContentInfo(ContentInfo.DATA_OID,
null), new X509Certificate[] { publicKey }, new SignerInfo[] { signerInfo });
pkcs7.encodeSignedData(out);
}
private static void signWholeOutputFile(byte[] zipData, OutputStream outputStream, X509Certificate publicKey,
PrivateKey privateKey) throws IOException, GeneralSecurityException {
// For a zip with no archive comment, the
// end-of-central-directory record will be 22 bytes long, so
// we expect to find the EOCD marker 22 bytes from the end.
if (zipData[zipData.length - 22] != 0x50 || zipData[zipData.length - 21] != 0x4b
|| zipData[zipData.length - 20] != 0x05 || zipData[zipData.length - 19] != 0x06) {
throw new IllegalArgumentException("zip data already has an archive comment");
}
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey);
signature.update(zipData, 0, zipData.length - 2);
ByteArrayOutputStream temp = new ByteArrayOutputStream();
// put a readable message and a null char at the start of the
// archive comment, so that tools that display the comment
// (hopefully) show something sensible.
// TODO: anything more useful we can put in this message?
byte[] message = "signed by SignApk".getBytes("UTF-8");
temp.write(message);
temp.write(0);
writeSignatureBlock(signature, publicKey, temp);
int total_size = temp.size() + 6;
if (total_size > 0xffff) {
throw new IllegalArgumentException("signature is too big for ZIP file comment");
}
// signature starts this many bytes from the end of the file
int signature_start = total_size - message.length - 1;
temp.write(signature_start & 0xff);
temp.write((signature_start >> 8) & 0xff);
// Why the 0xff bytes? In a zip file with no archive comment,
// bytes [-6:-2] of the file are the little-endian offset from
// the start of the file to the central directory. So for the
// two high bytes to be 0xff 0xff, the archive would have to
// be nearly 4GB in side. So it's unlikely that a real
// commentless archive would have 0xffs here, and lets us tell
// an old signed archive from a new one.
temp.write(0xff);
temp.write(0xff);
temp.write(total_size & 0xff);
temp.write((total_size >> 8) & 0xff);
temp.flush();
// Signature verification checks that the EOCD header is the
// last such sequence in the file (to avoid minzip finding a
// fake EOCD appended after the signature in its scan). The
// odds of producing this sequence by chance are very low, but
// let's catch it here if it does.
byte[] b = temp.toByteArray();
for (int i = 0; i < b.length - 3; ++i) {
if (b[i] == 0x50 && b[i + 1] == 0x4b && b[i + 2] == 0x05 && b[i + 3] == 0x06) {
throw new IllegalArgumentException("found spurious EOCD header at " + i);
}
}
outputStream.write(zipData, 0, zipData.length - 2);
outputStream.write(total_size & 0xff);
outputStream.write((total_size >> 8) & 0xff);
temp.writeTo(outputStream);
}
private static PrivateKey readPrivateKey(File file)
throws IOException, GeneralSecurityException {
DataInputStream input = new DataInputStream(new FileInputStream(file));
try {
byte[] bytes = new byte[(int) file.length()];
input.read(bytes);
// dont support encrypted keys atm
//KeySpec spec = decryptPrivateKey(bytes, file);
//if (spec == null) {
KeySpec spec = new PKCS8EncodedKeySpec(bytes);
//}
try {
return KeyFactory.getInstance("RSA").generatePrivate(spec);
} catch (InvalidKeySpecException ex) {
return KeyFactory.getInstance("DSA").generatePrivate(spec);
}
} finally {
input.close();
}
}
private static X509Certificate readPublicKey(File file)
throws IOException, GeneralSecurityException {
FileInputStream input = new FileInputStream(file);
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return (X509Certificate) cf.generateCertificate(input);
} finally {
input.close();
}
}
public static void main(String[] args) {
if (args.length < 4) {
System.out.println("MinSignAPK pemfile pk8file inzip outzip");
System.out.println("- only adds whole-file signature to zip");
return;
}
String pemFile = args[0];
String pk8File = args[1];
String inFile = args[2];
String outFile = args[3];
try {
X509Certificate publicKey = readPublicKey(new File(pemFile));
PrivateKey privateKey = readPrivateKey(new File(pk8File));
InputStream fis = new FileInputStream(inFile);
byte[] buffer = new byte[(int)(new File(inFile)).length()];
fis.read(buffer);
fis.close();
OutputStream fos = new FileOutputStream(outFile, false);
signWholeOutputFile(buffer, fos, publicKey, privateKey);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* Copyright (C) 2013 Jorrit "Chainfire" Jongma
* Copyright (C) 2013 The OmniROM Project
*/
/*
* This file is part of OpenDelta.
*
* OpenDelta is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenDelta is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenDelta. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <zlib.h>
#pragma pack(1)
struct local_header_struct {
uint32_t signature;
uint16_t extract_version;
uint16_t flags;
uint16_t compression_method;
uint16_t last_modified_time;
uint16_t last_modified_date;
uint32_t crc32;
uint32_t size_compressed;
uint32_t size_uncompressed;
uint16_t length_filename;
uint16_t length_extra;
// filename
// extra
};
typedef struct local_header_struct local_header_t;
#pragma pack(1)
struct data_descriptor_struct {
uint32_t signature;
uint32_t crc32;
uint32_t size_compressed;
uint32_t size_uncompressed;
};
typedef struct data_descriptor_struct data_descriptor_t;
#pragma pack(1)
struct central_header_struct {
uint32_t signature;
uint16_t version_made;
uint16_t version_needed;
uint16_t flags;
uint16_t compression_method;
uint16_t last_modified_time;
uint16_t last_modified_date;
uint32_t crc32;
uint32_t size_compressed;
uint32_t size_uncompressed;
uint16_t length_filename;
uint16_t length_extra;
uint16_t length_comment;
uint16_t disk_start;
uint16_t attr_internal;
uint32_t attr_external;
uint32_t offset;
// filename
// extra
// comment
};
typedef struct central_header_struct central_header_t;
#pragma pack(1)
struct central_footer_struct {
uint32_t signature;
uint16_t disk_number;
uint16_t disk_number_central_directory;
uint16_t central_directory_entries_this_disk;
uint16_t central_directory_entries_total;
uint32_t central_directory_size;
uint32_t central_directory_offset;
uint16_t length_comment;
// comment
};
typedef struct central_footer_struct central_footer_t;
#define MAGIC_LOCAL_HEADER 0x04034b50
#define MAGIC_DATA_DESCRIPTOR 0x08074b50
#define MAGIC_CENTRAL_HEADER 0x02014b50
#define MAGIC_CENTRAL_FOOTER 0x06054b50
static int xerror(char* message) {
fprintf(stderr, "%s\n", message);
return 0;
}
static int xseekread(int fd, off_t offset, void* buf, size_t bytes) {
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) return xerror("Seek failed");
if (read(fd, buf, bytes) != bytes) return xerror("Read failed");
return 1;
}
static int xseekwrite(int fd, off_t offset, void* buf, size_t bytes) {
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) return xerror("Seek failed");
if (write(fd, buf, bytes) != bytes) return xerror("Write failed");
return 1;
}
static int xfilecopy(int fdIn, int fdOut, off_t offsetIn, off_t offsetOut, size_t bytes) {
if ((offsetIn != (off_t)-1) && (lseek(fdIn, offsetIn, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
if ((offsetOut != (off_t)-1) && (lseek(fdOut, offsetOut, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
int CHUNK = 256 * 1024;
void* buf = malloc(CHUNK);
if (buf == NULL) return xerror("malloc failed");
size_t left = bytes;
while (left > 0) {
size_t wanted = (left < CHUNK) ? left : CHUNK;
size_t r = read(fdIn, buf, wanted);
if (r <= 0) return xerror("Read failed");
if (write(fdOut, buf, r) != r) return xerror("Write failed");
left -= r;
}
free(buf);
return 1;
}
static int xdecompress(int fdIn, int fdOut, off_t offsetIn, off_t offsetOut, size_t bytes) {
if ((offsetIn != (off_t)-1) && (lseek(fdIn, offsetIn, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
if ((offsetOut != (off_t)-1) && (lseek(fdOut, offsetOut, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
int CHUNK = 256 * 1024;
int ret;
unsigned have;
z_stream strm;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, -15);
if (ret != Z_OK) return xerror("ret != Z_OK");
do {
strm.avail_in = read(fdIn, in, CHUNK);
if (strm.avail_in < 0) {
(void)inflateEnd(&strm);
return xerror("Read failed");
}
if (strm.avail_in == 0) break;
strm.next_in = in;
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR) return xerror("Stream error");
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return xerror("DICT/DATA/MEM error");
}
have = CHUNK - strm.avail_out;
if (write(fdOut, out, have) != have) {
(void)inflateEnd(&strm);
return xerror("Write failed");
}
} while (strm.avail_out == 0);
} while (ret != Z_STREAM_END);
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? 1 : 0;
}
int zipadjust(char* filenameIn, char* filenameOut, int decompress) {
int ok = 0;
int fin = open(filenameIn, O_RDONLY);
if (fin > 0) {
unsigned int size = lseek(fin, 0, SEEK_END);
lseek(fin, 0, SEEK_SET);
printf("%d bytes\n", size);
char filename[1024];
central_footer_t central_footer;
uint32_t central_directory_in_position = 0;
uint32_t central_directory_in_size = 0;
uint32_t central_directory_out_size = 0;
int i;
for (i = size - 4; i >= 0; i--) {
uint32_t magic = 0;
if (!xseekread(fin, i, &magic, sizeof(uint32_t))) return 0;
if (magic == MAGIC_CENTRAL_FOOTER) {
printf("central footer @ %08X\n", i);
if (!xseekread(fin, i, &central_footer, sizeof(central_footer_t))) return 0;
central_header_t central_header;
if (!xseekread(fin, central_footer.central_directory_offset, &central_header, sizeof(central_header_t))) return 0;
if ( central_header.signature == MAGIC_CENTRAL_HEADER ) {
central_directory_in_position = central_footer.central_directory_offset;
central_directory_in_size = size - central_footer.central_directory_offset;
printf("central header @ %08X (%d)\n", central_footer.central_directory_offset, central_footer.central_directory_size);
break;
}
}
}
if (central_directory_in_position == 0) return 0;
unsigned char* central_directory_in = (unsigned char*)malloc(central_directory_in_size);
unsigned char* central_directory_out = (unsigned char*)malloc(central_directory_in_size);
if (!xseekread(fin, central_directory_in_position, central_directory_in, central_directory_in_size)) return 0;
memset(central_directory_out, 0, central_directory_in_size);
unlink(filenameOut);
int fout = open(filenameOut, O_CREAT | O_WRONLY, 0644);
if (fout > 0) {
uintptr_t central_directory_in_index = 0;
uintptr_t central_directory_out_index = 0;
central_header_t* central_header = NULL;
local_header_t local_header;
uint32_t out_index = 0;
while (1) {
central_header = (central_header_t*)&central_directory_in[central_directory_in_index];
if (central_header->signature != MAGIC_CENTRAL_HEADER) break;
filename[central_header->length_filename] = (char)0;
memcpy(filename, &central_directory_in[central_directory_in_index + sizeof(central_header_t)], central_header->length_filename);
printf("%s (%d --> %d) [%08X] (%d)\n", filename, central_header->size_uncompressed, central_header->size_compressed, central_header->crc32, central_header->length_extra + central_header->length_comment);
local_header_t local_header;
if (!xseekread(fin, central_header->offset, &local_header, sizeof(local_header_t))) return 0;
// save and update to next index before we clobber the data
uint16_t compression_method_old = central_header->compression_method;
uint32_t size_compressed_old = central_header->size_compressed;
uint32_t offset_old = central_header->offset;
uint32_t length_extra_old = central_header->length_extra;
central_directory_in_index += sizeof(central_header_t) + central_header->length_filename + central_header->length_extra + central_header->length_comment;
// copying, rewriting, and correcting local and central headers so all the information matches, and no data descriptors are necessary
central_header->offset = out_index;
central_header->flags = central_header->flags & !8;
if (decompress && (compression_method_old == 8)) {
central_header->compression_method = 0;
central_header->size_compressed = central_header->size_uncompressed;
}
central_header->length_extra = 0;
central_header->length_comment = 0;
local_header.compression_method = central_header->compression_method;
local_header.flags = central_header->flags;
local_header.crc32 = central_header->crc32;
local_header.size_uncompressed = central_header->size_uncompressed;
local_header.size_compressed = central_header->size_compressed;
local_header.length_extra = 0;
if (!xseekwrite(fout, out_index, &local_header, sizeof(local_header_t))) return 0;
out_index += sizeof(local_header_t);
if (!xseekwrite(fout, out_index, &filename[0], central_header->length_filename)) return 0;
out_index += central_header->length_filename;
if (decompress && (compression_method_old == 8)) {
if (!xdecompress(fin, fout, offset_old + sizeof(local_header_t) + central_header->length_filename + length_extra_old, out_index, size_compressed_old)) return 0;
} else {
if (!xfilecopy(fin, fout, offset_old + sizeof(local_header_t) + central_header->length_filename + length_extra_old, out_index, size_compressed_old)) return 0;
}
out_index += local_header.size_compressed;
memcpy(&central_directory_out[central_directory_out_index], central_header, sizeof(central_header_t) + central_header->length_filename);
central_directory_out_index += sizeof(central_header_t) + central_header->length_filename;
}
central_directory_out_size = central_directory_out_index;
central_footer.central_directory_size = central_directory_out_size;
central_footer.central_directory_offset = out_index;
central_footer.length_comment = 0;
if (!xseekwrite(fout, out_index, central_directory_out, central_directory_out_size)) return 0;
out_index += central_directory_out_size;
if (!xseekwrite(fout, out_index, &central_footer, sizeof(central_footer_t))) return 0;
printf("central header @ %08X (%d)\n", central_footer.central_directory_offset, central_footer.central_directory_size);
printf("central footer @ %08X\n", out_index);
close(fout);
ok = 1;
}
free(central_directory_in);
free(central_directory_out);
close(fin);
}
return ok;
}
/*
* Copyright (C) 2013 Jorrit "Chainfire" Jongma
* Copyright (C) 2013 The OmniROM Project
*/
/*
* This file is part of OpenDelta.
*
* OpenDelta is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenDelta is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenDelta. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ZIPADJUST_H
#define __ZIPADJUST_H
int zipadjust(char* filenameIn, char* filenameOut, int decompress);
#endif
/*
* Copyright (C) 2013 Jorrit "Chainfire" Jongma
* Copyright (C) 2013 The OmniROM Project
*/
/*
* This file is part of OpenDelta.
*
* OpenDelta is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenDelta is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenDelta. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include "zipadjust.h"
int main(int argc, char *argv[]) {
if (argc >= 3) {
if ((argc >= 4) && (strcmp(argv[1], "--decompress") == 0)) {
zipadjust(argv[2], argv[3], 1);
return 0;
} else {
zipadjust(argv[1], argv[2], 0);
return 0;
}
}
printf("zipadjust - Copyright (c) 2013 Jorrit Jongma (Chainfire)\n");
printf("\n");
printf("Usage: zipadjust [--decompress] input.zip output.zip\n");
printf("\n");
printf("Rewrites a zipfile removing all extra fields and comments (this includes the signapk whole-file signature), and synchronizing local headers with the central directory so no data descriptors are needed anymore. Optionally, the output zip is converted to only use STORE.\n");
printf("\n");
printf("Written to work specifically with Android OTA zip files, and does not cope with all possible zip file features and formats.\n");
return 0;
}
-----BEGIN CERTIFICATE-----
MIIEqDCCA5CgAwIBAgIJAJNurL4H8gHfMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
Fw0wODAyMjkwMTMzNDZaFw0zNTA3MTcwMTMzNDZaMIGUMQswCQYDVQQGEwJVUzET
MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
hvcNAQEBBQADggENADCCAQgCggEBANaTGQTexgskse3HYuDZ2CU+Ps1s6x3i/waM
qOi8qM1r03hupwqnbOYOuw+ZNVn/2T53qUPn6D1LZLjk/qLT5lbx4meoG7+yMLV4
wgRDvkxyGLhG9SEVhvA4oU6Jwr44f46+z4/Kw9oe4zDJ6pPQp8PcSvNQIg1QCAcy
4ICXF+5qBTNZ5qaU7Cyz8oSgpGbIepTYOzEJOmc3Li9kEsBubULxWBjf/gOBzAzU
RNps3cO4JFgZSAGzJWQTT7/emMkod0jb9WdqVA2BVMi7yge54kdVMxHEa5r3b97s
zI5p58ii0I54JiCUP5lyfTwE/nKZHZnfm644oLIXf6MdW2r+6R8CAQOjgfwwgfkw
HQYDVR0OBBYEFEhZAFY9JyxGrhGGBaR0GawJyowRMIHJBgNVHSMEgcEwgb6AFEhZ
AFY9JyxGrhGGBaR0GawJyowRoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJAJNurL4H8gHfMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHqvlozrUMRBBVEY0NqrrwFbinZa
J6cVosK0TyIUFf/azgMJWr+kLfcHCHJsIGnlw27drgQAvilFLAhLwn62oX6snb4Y
LCBOsVMR9FXYJLZW2+TcIkCRLXWG/oiVHQGo/rWuWkJgU134NDEFJCJGjDbiLCpe
+ZTWHdcwauTJ9pUbo8EvHRkU3cYfGmLaLfgn9gP+pWA7LFQNvXwBnDa6sppCccEX
31I828XzgXpJ4O+mDL1/dBd+ek8ZPUP0IgdyZm5MTYPhvVqGCHzzTy3sIeJFymwr
sBbmg2OAUNLEMO6nwmocSdN2ClirfxqCzJOLSDE4QyS9BAH6EhY6UFcOaE0=
-----END CERTIFICATE-----
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment