diff --git a/native/jni/magiskboot/compress.cpp b/native/jni/magiskboot/compress.cpp index 8779c663a..7195d5ceb 100644 --- a/native/jni/magiskboot/compress.cpp +++ b/native/jni/magiskboot/compress.cpp @@ -44,7 +44,7 @@ void decompress(char *infile, const char *outfile) { if (!COMPRESSED(type)) LOGE("Input file is not a compressed type!\n"); - cmp = std::move(unique_ptr(get_decoder(type))); + cmp.reset(get_decoder(type)); fprintf(stderr, "Detected format: [%s]\n", fmt2name[type]); /* 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(out_fd)); if (ext) *ext = '.'; } @@ -103,13 +104,14 @@ void compress(const char *method, const char *infile, const char *outfile) { * STDIN, output to .[ext] */ char *tmp = new char[strlen(infile) + 5]; 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); delete[] tmp; rm_in = true; } } 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(out_fd)); @@ -127,9 +129,6 @@ void compress(const char *method, const char *infile, const char *outfile) { unlink(infile); } - -/* Compression Streams */ - Compression *get_encoder(format_t type) { switch (type) { case XZ: @@ -184,7 +183,7 @@ GZStream::GZStream(int mode) : mode(mode), strm({}) { } 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() { @@ -237,7 +236,7 @@ BZStream::BZStream(int mode) : mode(mode), strm({}) { } 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() { @@ -304,7 +303,7 @@ LZMAStream::LZMAStream(int mode) : mode(mode), strm(LZMA_STREAM_INIT) { } 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() { @@ -394,6 +393,8 @@ LZ4FEncoder::~LZ4FEncoder() { bool LZ4FEncoder::write(const void *in, size_t size) { if (!outbuf) write_header(); + if (size == 0) + return true; auto inbuf = (const uint8_t *) in; size_t read, write; do { @@ -507,6 +508,8 @@ bool LZ4Encoder::write(const void *in, size_t size) { FilterOutStream::write("\x02\x21\x4c\x18", 4); init = true; } + if (size == 0) + return true; in_total += size; const char *inbuf = (const char *) in; size_t consumed; diff --git a/native/jni/magiskboot/ramdisk.cpp b/native/jni/magiskboot/ramdisk.cpp index 52f01a671..70feb670c 100644 --- a/native/jni/magiskboot/ramdisk.cpp +++ b/native/jni/magiskboot/ramdisk.cpp @@ -6,17 +6,29 @@ #include #include "magiskboot.h" +#include "compress.h" 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 { public: explicit magisk_cpio(const char *filename) : cpio_rw(filename) {} void patch(bool keepverity, bool keepforceencrypt); int test(); - char * sha1(); + char *sha1(); void restore(); void backup(const char *orig); + void compress(); }; 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 UNSUPPORT_PATCH 0x2 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) if (exists(file)) return UNSUPPORT_PATCH; @@ -202,6 +207,21 @@ void magisk_cpio::backup(const char *orig) { 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()); + output(encoder); + encoder.finalize(); + entries.clear(); + entries.insert(std::move(init)); + auto xz = new cpio_entry(ramdisk_xz); + xz->mode = S_IFREG; + static_cast(encoder.get_out())->release(xz->data, xz->filesize); + insert(xz); +} + int cpio_commands(int argc, char *argv[]) { char *incpio = argv[0]; ++argv; @@ -232,6 +252,8 @@ int cpio_commands(int argc, char *argv[]) { char *sha1 = cpio.sha1(); if (sha1) printf("%s\n", sha1); return 0; + } else if (strcmp(cmdv[0], "compress") == 0){ + cpio.compress(); } else if (cmdc == 2 && strcmp(cmdv[0], "exists") == 0) { exit(!cpio.exists(cmdv[1])); } else if (cmdc == 2 && strcmp(cmdv[0], "backup") == 0) { diff --git a/native/jni/utils/include/OutStream.h b/native/jni/utils/include/OutStream.h index 057f51c13..116bab307 100644 --- a/native/jni/utils/include/OutStream.h +++ b/native/jni/utils/include/OutStream.h @@ -19,6 +19,8 @@ public: 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 { return out ? out->write(buf, len) : false; } @@ -44,3 +46,38 @@ protected: int fd; 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 + 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; +};