From cf8f042a2052037b698ec39f9b18c5123a6235a4 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 13 Aug 2021 04:53:11 -0700 Subject: [PATCH] Cleanup magiskboot cpio code --- native/jni/Android.mk | 2 +- native/jni/external/Android.mk | 3 +- native/jni/{utils => magiskboot}/cpio.cpp | 84 ++++++++++------------- native/jni/magiskboot/cpio.hpp | 55 +++++++++++++++ native/jni/magiskboot/ramdisk.cpp | 67 +++++++++--------- native/jni/utils/include/cpio.hpp | 68 ------------------ 6 files changed, 127 insertions(+), 152 deletions(-) rename native/jni/{utils => magiskboot}/cpio.cpp (72%) create mode 100644 native/jni/magiskboot/cpio.hpp delete mode 100644 native/jni/utils/include/cpio.hpp diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 5daeb4512..93d06b0aa 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -97,7 +97,7 @@ LOCAL_SRC_FILES := \ magiskboot/dtb.cpp \ magiskboot/ramdisk.cpp \ magiskboot/pattern.cpp \ - utils/cpio.cpp + magiskboot/cpio.cpp LOCAL_LDFLAGS := -static include $(BUILD_EXECUTABLE) diff --git a/native/jni/external/Android.mk b/native/jni/external/Android.mk index 4dab7ee39..34985d154 100644 --- a/native/jni/external/Android.mk +++ b/native/jni/external/Android.mk @@ -3,8 +3,7 @@ LOCAL_PATH := $(call my-dir) # Header only library include $(CLEAR_VARS) LOCAL_MODULE:= libphmap -LOCAL_C_INCLUDES := $(LOCAL_PATH)/parallel-hashmap -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/parallel-hashmap include $(BUILD_STATIC_LIBRARY) # libxz.a diff --git a/native/jni/utils/cpio.cpp b/native/jni/magiskboot/cpio.cpp similarity index 72% rename from native/jni/utils/cpio.cpp rename to native/jni/magiskboot/cpio.cpp index 673df1b02..d71fbf8c5 100644 --- a/native/jni/utils/cpio.cpp +++ b/native/jni/magiskboot/cpio.cpp @@ -1,11 +1,10 @@ #include #include -#include -#include #include #include -#include + +#include "cpio.hpp" using namespace std; @@ -43,8 +42,11 @@ static uint32_t x8u(const char *hex) { return val; } -cpio_entry_base::cpio_entry_base(const cpio_newc_header *h) -: mode(x8u(h->mode)), uid(x8u(h->uid)), gid(x8u(h->gid)), filesize(x8u(h->filesize)) {}; +cpio_entry::cpio_entry(uint32_t mode) : mode(mode), uid(0), gid(0), filesize(0), data(nullptr) {} + +cpio_entry::cpio_entry(const cpio_newc_header *h) : +mode(x8u(h->mode)), uid(x8u(h->uid)), gid(x8u(h->gid)), filesize(x8u(h->filesize)), data(nullptr) +{} void cpio::dump(const char *file) { fprintf(stderr, "Dump cpio: [%s]\n", file); @@ -71,12 +73,12 @@ void cpio::rm(const char *name, bool r) { } } -static void extract_entry(const entry_map::value_type &e, const char *file) { +void cpio::extract_entry(const entry_map::value_type &e, const char *file) { fprintf(stderr, "Extract [%s] to [%s]\n", e.first.data(), file); unlink(file); rmdir(file); if (S_ISDIR(e.second->mode)) { - mkdir(file, e.second->mode & 0777); + ::mkdir(file, e.second->mode & 0777); } else if (S_ISREG(e.second->mode)) { int fd = creat(file, e.second->mode & 0777); xwrite(fd, e.second->data, e.second->filesize); @@ -148,11 +150,7 @@ void cpio::dump(FILE *out) { fclose(out); } -cpio_rw::cpio_rw(const char *file) { - load_cpio(file); -} - -void cpio_rw::load_cpio(const char *file) { +void cpio::load_cpio(const char *file) { char *buf; size_t sz; mmap_ro(file, buf, sz); @@ -161,54 +159,49 @@ void cpio_rw::load_cpio(const char *file) { munmap(buf, sz); } -void cpio_rw::insert(cpio_entry *e) { - auto ex = entries.extract(e->filename); - if (!ex) { - entries[e->filename].reset(e); +void cpio::insert(string_view name, cpio_entry *e) { + auto it = entries.find(name); + if (it != entries.end()) { + it->second.reset(e); } else { - ex.key() = e->filename; - ex.mapped().reset(e); - entries.insert(std::move(ex)); + entries.emplace(name, e); } } -void cpio_rw::add(mode_t mode, const char *name, const char *file) { +void cpio::add(mode_t mode, const char *name, const char *file) { void *buf; size_t sz; mmap_ro(file, buf, sz); - auto e = new cpio_entry(name, S_IFREG | mode); + auto e = new cpio_entry(S_IFREG | mode); e->filesize = sz; e->data = xmalloc(sz); memcpy(e->data, buf, sz); munmap(buf, sz); - insert(e); + insert(name, e); fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode); } -void cpio_rw::mkdir(mode_t mode, const char *name) { - insert(new cpio_entry(name, S_IFDIR | mode)); +void cpio::mkdir(mode_t mode, const char *name) { + insert(name, new cpio_entry(S_IFDIR | mode)); fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode); } -void cpio_rw::ln(const char *target, const char *name) { - auto e = new cpio_entry(name, S_IFLNK); +void cpio::ln(const char *target, const char *name) { + auto e = new cpio_entry(S_IFLNK); e->filesize = strlen(target); e->data = strdup(target); - insert(e); + insert(name, e); fprintf(stderr, "Create symlink [%s] -> [%s]\n", name, target); } -void cpio_rw::mv(entry_map::iterator &it, const char *to) { - fprintf(stderr, "Move [%s] -> [%s]\n", it->first.data(), to); - auto ex = entries.extract(it); - auto &name = static_cast(ex.mapped().get())->filename; - name = to; - ex.key() = name; - entries.erase(name); - entries.insert(std::move(ex)); +void cpio::mv(entry_map::iterator &it, const char *name) { + fprintf(stderr, "Move [%s] -> [%s]\n", it->first.data(), name); + auto e = it->second.release(); + entries.erase(it); + insert(name, e); } -bool cpio_rw::mv(const char *from, const char *to) { +bool cpio::mv(const char *from, const char *to) { auto it = entries.find(from); if (it != entries.end()) { mv(it, to); @@ -220,26 +213,23 @@ bool cpio_rw::mv(const char *from, const char *to) { #define pos_align(p) p = do_align(p, 4) -void cpio_rw::load_cpio(const char *buf, size_t sz) { +void cpio::load_cpio(const char *buf, size_t sz) { size_t pos = 0; - const cpio_newc_header *header; - unique_ptr entry; while (pos < sz) { - header = reinterpret_cast(buf + pos); - entry = make_unique(header); - pos += sizeof(*header); - string_view name_view(buf + pos); + auto header = reinterpret_cast(buf + pos); + pos += sizeof(cpio_newc_header); + string_view name(buf + pos); pos += x8u(header->namesize); pos_align(pos); - if (name_view == "." || name_view == "..") + if (name == "." || name == "..") continue; - if (name_view == "TRAILER!!!") + if (name == "TRAILER!!!") break; - entry->filename = name_view; + auto entry = new cpio_entry(header); entry->data = xmalloc(entry->filesize); memcpy(entry->data, buf + pos, entry->filesize); pos += entry->filesize; - entries[entry->filename] = std::move(entry); + insert(name, entry); pos_align(pos); } } diff --git a/native/jni/magiskboot/cpio.hpp b/native/jni/magiskboot/cpio.hpp new file mode 100644 index 000000000..8a1b9ab64 --- /dev/null +++ b/native/jni/magiskboot/cpio.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include +#include +#include + +struct cpio_newc_header; + +struct cpio_entry { + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t filesize; + void *data; + + explicit cpio_entry(uint32_t mode = 0); + explicit cpio_entry(const cpio_newc_header *h); + ~cpio_entry() { free(data); } +}; + +class cpio { +public: + struct StringCmp { + using is_transparent = void; + bool operator()(std::string_view a, std::string_view b) const { + return a < b; + } + }; + using entry_map = std::map, StringCmp>; + + void load_cpio(const char *file); + void dump(const char *file); + void rm(const char *name, bool r = false); + void extract(); + bool extract(const char *name, const char *file); + bool exists(const char *name); + void add(mode_t mode, const char *name, const char *file); + void mkdir(mode_t mode, const char *name); + void ln(const char *target, const char *name); + bool mv(const char *from, const char *to); + +protected: + entry_map entries; + + static void extract_entry(const entry_map::value_type &e, const char *file); + void rm(entry_map::iterator &it); + void mv(entry_map::iterator &it, const char *name); + +private: + void dump(FILE *out); + void insert(std::string_view name, cpio_entry *e); + void load_cpio(const char *buf, size_t sz); +}; diff --git a/native/jni/magiskboot/ramdisk.cpp b/native/jni/magiskboot/ramdisk.cpp index 9e8dd9887..7b928e0af 100644 --- a/native/jni/magiskboot/ramdisk.cpp +++ b/native/jni/magiskboot/ramdisk.cpp @@ -1,6 +1,6 @@ #include -#include +#include "cpio.hpp" #include "magiskboot.hpp" #include "compress.hpp" @@ -14,9 +14,8 @@ static const char *MAGISK_LIST[] = { ".backup/.magisk", "init.magisk.rc", "overlay/init.magisk.rc" }; -class magisk_cpio : public cpio_rw { +class magisk_cpio : public cpio { public: - using cpio_rw::cpio_rw; void patch(); int test(); char *sha1(); @@ -95,7 +94,7 @@ char *magisk_cpio::sha1() { } } else if (e.first == ".backup/.magisk") { for_each_line(line, e.second->data, e.second->filesize) { - if (strncmp(line, "SHA1=", 5) == 0) { + if (str_starts(line, "SHA1=")) { strncpy(sha1, line + 5, 40); sha1[40] = '\0'; return strdup(sha1); @@ -114,15 +113,16 @@ for (str = (char *) buf; str < (char *) buf + size; str = str += strlen(str) + 1 void magisk_cpio::restore() { if (auto it = entries.find(".backup/.rmlist"); it != entries.end()) { char *file; - for_each_str(file, it->second->data, it->second->filesize) - rm(file, false); + for_each_str(file, it->second->data, it->second->filesize) { + rm(file); + } rm(it); } for (auto it = entries.begin(); it != entries.end();) { auto cur = it++; if (str_starts(cur->first, ".backup")) { - if (cur->first.length() == 7 || cur->first.substr(8) == ".magisk") { + if (cur->first.length() == 7 || &cur->first[8] == ".magisk"sv) { rm(cur); } else { mv(cur, &cur->first[8]); @@ -140,15 +140,15 @@ void magisk_cpio::restore() { void magisk_cpio::backup(const char *orig) { if (access(orig, R_OK)) return; - entry_map bkup_entries; - string remv; - auto b = new cpio_entry(".backup", S_IFDIR); - bkup_entries[b->filename].reset(b); + entry_map backups; + string rm_list; + backups.emplace(".backup", new cpio_entry(S_IFDIR)); - magisk_cpio o(orig); + magisk_cpio o; + o.load_cpio(orig); - // Remove possible backups in original ramdisk + // Remove existing backups in original ramdisk o.rm(".backup", true); rm(".backup", true); @@ -157,7 +157,7 @@ void magisk_cpio::backup(const char *orig) { while (lhs != o.entries.end() || rhs != entries.end()) { int res; - bool backup = false; + bool do_backup = false; if (lhs != o.entries.end() && rhs != entries.end()) { res = lhs->first.compare(rhs->first); } else if (lhs == o.entries.end()) { @@ -167,29 +167,28 @@ void magisk_cpio::backup(const char *orig) { } if (res < 0) { - // Something is missing in new ramdisk, backup! - backup = true; + // Something is missing in new ramdisk, do_backup! + do_backup = true; fprintf(stderr, "Backup missing entry: "); } else if (res == 0) { if (lhs->second->filesize != rhs->second->filesize || memcmp(lhs->second->data, rhs->second->data, lhs->second->filesize) != 0) { // Not the same! - backup = true; + do_backup = true; fprintf(stderr, "Backup mismatch entry: "); } } else { // Something new in ramdisk - remv += rhs->first; - remv += (char) '\0'; + rm_list += rhs->first; + rm_list += (char) '\0'; fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", rhs->first.data()); } - if (backup) { - string back_name(".backup/"); - back_name += lhs->first; - fprintf(stderr, "[%s] -> [%s]\n", lhs->first.data(), back_name.data()); - auto ex = static_cast(lhs->second.release()); - ex->filename = back_name; - bkup_entries[ex->filename].reset(ex); + + if (do_backup) { + string name = ".backup/" + lhs->first; + fprintf(stderr, "[%s] -> [%s]\n", lhs->first.data(), name.data()); + auto e = lhs->second.release(); + backups.emplace(name, e); } // Increment positions @@ -202,16 +201,16 @@ void magisk_cpio::backup(const char *orig) { } } - if (!remv.empty()) { - auto rmlist = new cpio_entry(".backup/.rmlist", S_IFREG); - rmlist->filesize = remv.length(); - rmlist->data = xmalloc(remv.length()); - memcpy(rmlist->data, remv.data(), remv.length()); - bkup_entries[rmlist->filename].reset(rmlist); + if (!rm_list.empty()) { + auto rm_list_file = new cpio_entry(S_IFREG); + rm_list_file->filesize = rm_list.length(); + rm_list_file->data = xmalloc(rm_list.length()); + memcpy(rm_list_file->data, rm_list.data(), rm_list.length()); + backups.emplace(".backup/.rmlist", rm_list_file); } - if (bkup_entries.size() > 1) - entries.merge(bkup_entries); + if (backups.size() > 1) + entries.merge(backups); } int cpio_commands(int argc, char *argv[]) { diff --git a/native/jni/utils/include/cpio.hpp b/native/jni/utils/include/cpio.hpp deleted file mode 100644 index 145a56260..000000000 --- a/native/jni/utils/include/cpio.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include - -struct cpio_newc_header; - -struct cpio_entry_base { - uint32_t mode = 0; - uint32_t uid = 0; - uint32_t gid = 0; - uint32_t filesize = 0; - - void *data = nullptr; - - cpio_entry_base() : mode(0), uid(0), gid(0), filesize(0) {}; - explicit cpio_entry_base(const cpio_newc_header *h); - virtual ~cpio_entry_base() = default; -}; - -struct cpio_entry : public cpio_entry_base { - std::string filename; - - cpio_entry() = default; - explicit cpio_entry(const char *name, uint32_t mode) : filename(name) { - this->mode = mode; - } - explicit cpio_entry(const cpio_newc_header *h) : cpio_entry_base(h) {} - - ~cpio_entry() override { free(data); }; -}; - -typedef std::map> entry_map; - -class cpio { -public: - void dump(const char *file); - void rm(const char *name, bool r = false); - void extract(); - bool extract(const char *name, const char *file); - bool exists(const char *name); - -protected: - entry_map entries; - void rm(entry_map::iterator &it); - void dump(FILE *out); -}; - -class cpio_rw : public cpio { -public: - cpio_rw() = default; - explicit cpio_rw(const char *file); - void load_cpio(const char *file); - void add(mode_t mode, const char *name, const char *file); - void mkdir(mode_t mode, const char *name); - void ln(const char *target, const char *name); - bool mv(const char *from, const char *to); - -protected: - void insert(cpio_entry *e); - void mv(entry_map::iterator &it, const char *to); - void load_cpio(const char *buf, size_t sz); -};