Add ramdisk compression option

This commit is contained in:
topjohnwu 2019-02-23 15:04:15 -05:00
parent 267c59b1f1
commit 9c89e56c56
3 changed files with 80 additions and 18 deletions

View File

@ -44,7 +44,7 @@ void decompress(char *infile, const char *outfile) {
if (!COMPRESSED(type)) if (!COMPRESSED(type))
LOGE("Input file is not a compressed type!\n"); LOGE("Input file is not a compressed type!\n");
cmp = std::move(unique_ptr<Compression>(get_decoder(type))); cmp.reset(get_decoder(type));
fprintf(stderr, "Detected format: [%s]\n", fmt2name[type]); fprintf(stderr, "Detected format: [%s]\n", fmt2name[type]);
/* If user does not provide outfile, infile has to be either /* If user does not provide outfile, infile has to be either
@ -66,7 +66,8 @@ void decompress(char *infile, const char *outfile) {
} }
} }
out_fd = strcmp(outfile, "-") == 0 ? STDOUT_FILENO : creat(outfile, 0644); out_fd = strcmp(outfile, "-") == 0 ?
STDOUT_FILENO : xopen(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
cmp->set_out(make_unique<FDOutStream>(out_fd)); cmp->set_out(make_unique<FDOutStream>(out_fd));
if (ext) *ext = '.'; if (ext) *ext = '.';
} }
@ -103,13 +104,14 @@ void compress(const char *method, const char *infile, const char *outfile) {
* STDIN, output to <infile>.[ext] */ * STDIN, output to <infile>.[ext] */
char *tmp = new char[strlen(infile) + 5]; char *tmp = new char[strlen(infile) + 5];
sprintf(tmp, "%s%s", infile, fmt2ext[it->second]); sprintf(tmp, "%s%s", infile, fmt2ext[it->second]);
out_fd = creat(tmp, 0644); out_fd = xopen(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
fprintf(stderr, "Compressing to [%s]\n", tmp); fprintf(stderr, "Compressing to [%s]\n", tmp);
delete[] tmp; delete[] tmp;
rm_in = true; rm_in = true;
} }
} else { } else {
out_fd = strcmp(outfile, "-") == 0 ? STDOUT_FILENO : creat(outfile, 0644); out_fd = strcmp(outfile, "-") == 0 ?
STDOUT_FILENO : xopen(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
} }
cmp->set_out(make_unique<FDOutStream>(out_fd)); cmp->set_out(make_unique<FDOutStream>(out_fd));
@ -127,9 +129,6 @@ void compress(const char *method, const char *infile, const char *outfile) {
unlink(infile); unlink(infile);
} }
/* Compression Streams */
Compression *get_encoder(format_t type) { Compression *get_encoder(format_t type) {
switch (type) { switch (type) {
case XZ: case XZ:
@ -184,7 +183,7 @@ GZStream::GZStream(int mode) : mode(mode), strm({}) {
} }
bool GZStream::write(const void *in, size_t size) { bool GZStream::write(const void *in, size_t size) {
return write(in, size, Z_NO_FLUSH); return size ? write(in, size, Z_NO_FLUSH) : true;
} }
uint64_t GZStream::finalize() { uint64_t GZStream::finalize() {
@ -237,7 +236,7 @@ BZStream::BZStream(int mode) : mode(mode), strm({}) {
} }
bool BZStream::write(const void *in, size_t size) { bool BZStream::write(const void *in, size_t size) {
return write(in, size, BZ_RUN); return size ? write(in, size, BZ_RUN) : true;
} }
uint64_t BZStream::finalize() { uint64_t BZStream::finalize() {
@ -304,7 +303,7 @@ LZMAStream::LZMAStream(int mode) : mode(mode), strm(LZMA_STREAM_INIT) {
} }
bool LZMAStream::write(const void *in, size_t size) { bool LZMAStream::write(const void *in, size_t size) {
return write(in, size, LZMA_RUN); return size ? write(in, size, LZMA_RUN) : true;
} }
uint64_t LZMAStream::finalize() { uint64_t LZMAStream::finalize() {
@ -394,6 +393,8 @@ LZ4FEncoder::~LZ4FEncoder() {
bool LZ4FEncoder::write(const void *in, size_t size) { bool LZ4FEncoder::write(const void *in, size_t size) {
if (!outbuf) if (!outbuf)
write_header(); write_header();
if (size == 0)
return true;
auto inbuf = (const uint8_t *) in; auto inbuf = (const uint8_t *) in;
size_t read, write; size_t read, write;
do { do {
@ -507,6 +508,8 @@ bool LZ4Encoder::write(const void *in, size_t size) {
FilterOutStream::write("\x02\x21\x4c\x18", 4); FilterOutStream::write("\x02\x21\x4c\x18", 4);
init = true; init = true;
} }
if (size == 0)
return true;
in_total += size; in_total += size;
const char *inbuf = (const char *) in; const char *inbuf = (const char *) in;
size_t consumed; size_t consumed;

View File

@ -6,17 +6,29 @@
#include <cpio.h> #include <cpio.h>
#include "magiskboot.h" #include "magiskboot.h"
#include "compress.h"
using namespace std; using namespace std;
static const char *ramdisk_xz = "ramdisk.cpio.xz";
static const char *UNSUPPORT_LIST[] =
{ "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc",
"boot/sbin/launch_daemonsu.sh" };
static const char *MAGISK_LIST[] =
{ ".backup/.magisk", "init.magisk.rc",
"overlay/init.magisk.rc", ramdisk_xz };
class magisk_cpio : public cpio_rw { class magisk_cpio : public cpio_rw {
public: public:
explicit magisk_cpio(const char *filename) : cpio_rw(filename) {} explicit magisk_cpio(const char *filename) : cpio_rw(filename) {}
void patch(bool keepverity, bool keepforceencrypt); void patch(bool keepverity, bool keepforceencrypt);
int test(); int test();
char * sha1(); char *sha1();
void restore(); void restore();
void backup(const char *orig); void backup(const char *orig);
void compress();
}; };
void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) {
@ -47,13 +59,6 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) {
#define MAGISK_PATCH 0x1 #define MAGISK_PATCH 0x1
#define UNSUPPORT_PATCH 0x2 #define UNSUPPORT_PATCH 0x2
int magisk_cpio::test() { int magisk_cpio::test() {
static const char *UNSUPPORT_LIST[] =
{ "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc",
"boot/sbin/launch_daemonsu.sh" };
static const char *MAGISK_LIST[] =
{ ".backup/.magisk", "init.magisk.rc",
"overlay/init.magisk.rc" };
for (auto file : UNSUPPORT_LIST) for (auto file : UNSUPPORT_LIST)
if (exists(file)) if (exists(file))
return UNSUPPORT_PATCH; return UNSUPPORT_PATCH;
@ -202,6 +207,21 @@ void magisk_cpio::backup(const char *orig) {
entries.merge(bkup_entries); entries.merge(bkup_entries);
} }
void magisk_cpio::compress() {
fprintf(stderr, "Compressing cpio -> [%s]\n", ramdisk_xz);
auto init = entries.extract("init");
XZEncoder encoder;
encoder.set_out(make_unique<BufOutStream>());
output(encoder);
encoder.finalize();
entries.clear();
entries.insert(std::move(init));
auto xz = new cpio_entry(ramdisk_xz);
xz->mode = S_IFREG;
static_cast<BufOutStream *>(encoder.get_out())->release(xz->data, xz->filesize);
insert(xz);
}
int cpio_commands(int argc, char *argv[]) { int cpio_commands(int argc, char *argv[]) {
char *incpio = argv[0]; char *incpio = argv[0];
++argv; ++argv;
@ -232,6 +252,8 @@ int cpio_commands(int argc, char *argv[]) {
char *sha1 = cpio.sha1(); char *sha1 = cpio.sha1();
if (sha1) printf("%s\n", sha1); if (sha1) printf("%s\n", sha1);
return 0; return 0;
} else if (strcmp(cmdv[0], "compress") == 0){
cpio.compress();
} else if (cmdc == 2 && strcmp(cmdv[0], "exists") == 0) { } else if (cmdc == 2 && strcmp(cmdv[0], "exists") == 0) {
exit(!cpio.exists(cmdv[1])); exit(!cpio.exists(cmdv[1]));
} else if (cmdc == 2 && strcmp(cmdv[0], "backup") == 0) { } else if (cmdc == 2 && strcmp(cmdv[0], "backup") == 0) {

View File

@ -19,6 +19,8 @@ public:
void set_out(strm_ptr &&ptr) { out = std::move(ptr); } void set_out(strm_ptr &&ptr) { out = std::move(ptr); }
OutStream *get_out() { return out.get(); }
bool write(const void *buf, size_t len) override { bool write(const void *buf, size_t len) override {
return out ? out->write(buf, len) : false; return out ? out->write(buf, len) : false;
} }
@ -44,3 +46,38 @@ protected:
int fd; int fd;
bool close; bool close;
}; };
class BufOutStream : public OutStream {
public:
BufOutStream() : buf(nullptr), off(0), cap(0) {};
bool write(const void *b, size_t len) override {
bool resize = false;
while (off + len > cap) {
cap = cap ? cap << 1 : 1 << 19;
resize = true;
}
if (resize)
buf = (char *) xrealloc(buf, cap);
memcpy(buf + off, b, len);
off += len;
return true;
}
template <typename T>
void release(void *&b, T &len) {
b = buf;
len = off;
buf = nullptr;
off = cap = 0;
}
~BufOutStream() override {
free(buf);
}
protected:
char *buf;
size_t off;
size_t cap;
};