diff --git a/native/jni/magiskboot/cpio.cpp b/native/jni/magiskboot/cpio.cpp index 481e69336..095800f04 100644 --- a/native/jni/magiskboot/cpio.cpp +++ b/native/jni/magiskboot/cpio.cpp @@ -3,7 +3,7 @@ #include #include #include - +#include #include #include @@ -30,20 +30,10 @@ static uint32_t x8u(char *hex) { return val; } -cpio_entry::cpio_entry(int fd, cpio_newc_header &header) { - // ino = x8u(header.ino); - mode = x8u(header.mode); - uid = x8u(header.uid); - gid = x8u(header.gid); - // nlink = x8u(header.nlink); - // mtime = x8u(header.mtime); - filesize = x8u(header.filesize); - // devmajor = x8u(header.devmajor); - // devminor = x8u(header.devminor); - // rdevmajor = x8u(header.rdevmajor); - // rdevminor = x8u(header.rdevminor); +cpio_entry::cpio_entry(int fd, cpio_newc_header &header) +: mode(x8u(header.mode)), uid(x8u(header.uid)), gid(x8u(header.gid)), +filesize(x8u(header.filesize)) { uint32_t namesize = x8u(header.namesize); - // check = x8u(header.check); filename.resize(namesize - 1); xxread(fd, &filename[0], namesize); parse_align(); @@ -63,27 +53,18 @@ cpio::cpio(const char *filename) { if (fd < 0) return; fprintf(stderr, "Loading cpio: [%s]\n", filename); cpio_newc_header header; - cpio_entry *entry; - int i = 0; + unique_ptr entry; while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) { - entry = new cpio_entry(fd, header); - if (entry->filename == "." || entry->filename == ".." || entry->filename == "TRAILER!!!") { - bool trailer = entry->filename[0] == 'T'; - delete entry; - if (trailer) - break; + entry = std::make_unique(fd, header); + if (entry->filename == "." || entry->filename == "..") continue; - } - arr.push_back(entry); + if (entry->filename == "TRAILER!!!") + break; + entries.push_back(std::move(entry)); } close(fd); } -cpio::~cpio() { - for (auto &e : arr) - delete e; -} - #define dump_align() write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), 4)) void cpio::dump(const char *file) { fprintf(stderr, "Dump cpio: [%s]\n", file); @@ -91,7 +72,7 @@ void cpio::dump(const char *file) { char header[111]; sort(); int fd = creat(file, 0644); - for (auto &e : arr) { + for (auto &e : entries) { sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", inode++, // e->ino e->mode, @@ -125,50 +106,52 @@ void cpio::dump(const char *file) { } int cpio::find(const char *name) { - for (int i = 0; i < arr.size(); ++i) { - if (!arr[i]) + for (int i = 0; i < entries.size(); ++i) { + if (!entries[i]) continue; - if (arr[i]->filename == name) + if (entries[i]->filename == name) return i; } return -1; } void cpio::insert(cpio_entry *e) { + auto ue = unique_ptr(e); + insert(ue); +} + +void cpio::insert(unique_ptr &e) { int i = find(e->filename.c_str()); if (i >= 0) { - delete arr[i]; - arr[i] = e; + entries[i] = std::move(e); } else { - arr.push_back(e); + entries.push_back(std::move(e)); } } void cpio::rm(const char *name, bool r) { size_t len = strlen(name); - for (auto &e : arr) { + for (auto &e : entries) { if (!e) continue; if (e->filename.compare(0, len, name) == 0 && ((r && e->filename[len] == '/') || e->filename[len] == '\0')) { fprintf(stderr, "Remove [%s]\n", e->filename.c_str()); - delete e; - e = nullptr; - if (!r) - return; + e.reset(); + if (!r) return; } } } void cpio::makedir(mode_t mode, const char *name) { - auto e = new cpio_entry(name); + auto e = make_unique(name); e->mode = S_IFDIR | mode; insert(e); fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode); } void cpio::ln(const char *target, const char *name) { - auto e = new cpio_entry(name); + auto e = make_unique(name); e->mode = S_IFLNK; e->filesize = strlen(target); e->data = strdup(target); @@ -177,14 +160,15 @@ void cpio::ln(const char *target, const char *name) { } void cpio::add(mode_t mode, const char *name, const char *file) { - int fd = xopen(file, O_RDONLY); - auto e = new cpio_entry(name); + void *buf; + size_t sz; + mmap_ro(file, &buf, &sz); + auto e = make_unique(name); e->mode = S_IFREG | mode; - e->filesize = lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); - e->data = xmalloc(e->filesize); - xxread(fd, e->data, e->filesize); - close(fd); + e->filesize = sz; + e->data = xmalloc(sz); + memcpy(e->data, buf, sz); + munmap(buf, sz); insert(e); fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode); } @@ -192,12 +176,10 @@ void cpio::add(mode_t mode, const char *name, const char *file) { bool cpio::mv(const char *from, const char *to) { int f = find(from), t = find(to); if (f >= 0) { - if (t > 0) { - delete arr[t]; - arr[t] = nullptr; - } + if (t > 0) + entries[t].reset(); fprintf(stderr, "Move [%s] -> [%s]\n", from, to); - arr[f]->filename = to; + entries[f]->filename = to; return true; } fprintf(stderr, "Cannot find entry %s\n", from); @@ -225,16 +207,16 @@ static void extract_entry(cpio_entry *e, const char *file) { } void cpio::extract() { - for (auto &e : arr) { + for (auto &e : entries) { if (!e) continue; - extract_entry(e, e->filename.c_str()); + extract_entry(e.get(), e->filename.c_str()); } } bool cpio::extract(const char *name, const char *file) { int i = find(name); if (i > 0) { - extract_entry(arr[i], file); + extract_entry(entries[i].get(), file); return true; } fprintf(stderr, "Cannot find the file entry [%s]\n", name); @@ -242,13 +224,15 @@ bool cpio::extract(const char *name, const char *file) { } void cpio::sort() { - std::sort(arr.begin(), arr.end(), [] (auto a, auto b) -> bool { - if (a == b || a == nullptr) + std::sort(entries.begin(), entries.end(), [] + (const unique_ptr &a, const unique_ptr &b) -> bool { + if (a == b || !a) return false; - if (b == nullptr) + if (!b) return true; - return a->filename.compare(b->filename) < 0; + return a->filename < b->filename; }); - while (arr.back() == nullptr) - arr.pop_back(); + + while (!entries.back()) + entries.pop_back(); } diff --git a/native/jni/magiskboot/cpio.h b/native/jni/magiskboot/cpio.h index 36dcf754b..eb09cbc98 100644 --- a/native/jni/magiskboot/cpio.h +++ b/native/jni/magiskboot/cpio.h @@ -4,6 +4,7 @@ #include #include #include +#include struct cpio_newc_header { char magic[6]; @@ -23,20 +24,12 @@ struct cpio_newc_header { } __attribute__((packed)); struct cpio_entry { - // uint32_t ino; uint32_t mode = 0; uint32_t uid = 0; uint32_t gid = 0; - // uint32_t nlink; - // uint32_t mtime; uint32_t filesize = 0; - // uint32_t devmajor; - // uint32_t devminor; - // uint32_t rdevmajor; - // uint32_t rdevminor; - // uint32_t namesize; - // uint32_t check; -// char *filename = nullptr; + + /* Dynamic data */ std::string filename; void *data = nullptr; @@ -49,10 +42,10 @@ struct cpio_entry { class cpio { public: explicit cpio(const char *filename); - ~cpio(); void dump(const char *file); int find(const char *name); void insert(cpio_entry *e); + void insert(std::unique_ptr &e); void rm(const char *name, bool r = false); void makedir(mode_t mode, const char *name); void ln(const char *target, const char *name); @@ -63,7 +56,7 @@ public: void sort(); protected: - std::vector arr; + std::vector > entries; }; #endif diff --git a/native/jni/magiskboot/ramdisk.cpp b/native/jni/magiskboot/ramdisk.cpp index 8c50034fd..9c6e9854e 100644 --- a/native/jni/magiskboot/ramdisk.cpp +++ b/native/jni/magiskboot/ramdisk.cpp @@ -22,9 +22,8 @@ public: void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { fprintf(stderr, "Patch with flag KEEPVERITY=[%s] KEEPFORCEENCRYPT=[%s]\n", keepverity ? "true" : "false", keepforceencrypt ? "true" : "false"); - for (auto &e : arr) { - if (!e) - continue; + for (auto &e : entries) { + if (!e) continue; bool fstab = (!keepverity || !keepforceencrypt) && !str_starts(e->filename, ".backup") && str_contains(e->filename, "fstab") && S_ISREG(e->mode); @@ -33,8 +32,7 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { patch_verity(&e->data, &e->filesize, 1); } else if (e->filename == "verity_key") { fprintf(stderr, "Remove [verity_key]\n"); - delete e; - e = nullptr; + e.reset(); continue; } } @@ -73,7 +71,7 @@ for (line = (char *) buf; line < (char *) buf + size && line[0]; line = strchr(l char *magisk_cpio::sha1() { char sha1[41]; char *line; - for (auto &e : arr) { + for (auto &e : entries) { if (!e) continue; if (e->filename == "init.magisk.rc" || e->filename == "overlay/init.magisk.rc") { for_each_line(line, e->data, e->filesize) { @@ -99,7 +97,7 @@ char *magisk_cpio::sha1() { } void magisk_cpio::restore() { - for (auto &e : arr) { + for (auto &e : entries) { if (!e) continue; if (str_starts(e->filename, ".backup")) { if (e->filename[7] == '\0') continue; @@ -122,17 +120,14 @@ void magisk_cpio::restore() { rm("magisk", true); } +#define lhs o.entries[i] +#define rhs entries[j] void magisk_cpio::backup(const char *orig) { - vector bak; - cpio_entry *m, *n, *rem; - char buf[PATH_MAX]; + vector > bkup_entries; + string remv; - m = new cpio_entry(".backup"); - m->mode = S_IFDIR; - bak.push_back(m); - - rem = new cpio_entry(".backup/.rmlist"); - rem->mode = S_IFREG; + bkup_entries.emplace_back(new cpio_entry(".backup")); + bkup_entries.back()->mode = S_IFDIR; magisk_cpio o(orig); @@ -146,59 +141,63 @@ void magisk_cpio::backup(const char *orig) { // Start comparing size_t i = 0, j = 0; - while(i != o.arr.size() || j != arr.size()) { + while(i != o.entries.size() || j != entries.size()) { int res; bool backup = false; - if (i != o.arr.size() && j != arr.size()) { - m = o.arr[i]; - n = arr[j]; - res = m->filename.compare(n->filename); - } else if (i == o.arr.size()) { - n = arr[j]; + if (i != o.entries.size() && j != entries.size()) { + res = lhs->filename.compare(rhs->filename); + } else if (i == o.entries.size()) { res = 1; - } else if (j == arr.size()) { - m = o.arr[i]; + } else if (j == entries.size()) { res = -1; } if (res < 0) { // Something is missing in new ramdisk, backup! - ++i; backup = true; fprintf(stderr, "Backup missing entry: "); } else if (res == 0) { - ++i; ++j; - if (m->filesize == n->filesize && memcmp(m->data, n->data, m->filesize) == 0) - continue; - // Not the same! - backup = true; - fprintf(stderr, "Backup mismatch entry: "); + if (memcmp(lhs->data, rhs->data, lhs->filesize) != 0) { + // Not the same! + backup = true; + fprintf(stderr, "Backup mismatch entry: "); + } } else { - // Something new in ramdisk, record in rem - ++j; - rem->data = xrealloc(rem->data, rem->filesize + n->filename.size()); - memcpy((char *) rem->data + rem->filesize, n->filename.c_str(), n->filename.size()); - rem->filesize += n->filename.size(); - fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename.c_str()); + // Something new in ramdisk + remv += rhs->filename; + remv += (char) '\0'; + fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", rhs->filename.c_str()); } if (backup) { - sprintf(buf, ".backup/%s", m->filename.c_str()); - fprintf(stderr, "[%s] -> [%s]\n", m->filename.c_str(), buf); - m->filename = buf; - bak.push_back(m); - // NULL the original entry, so it won't be freed - o.arr[i - 1] = nullptr; + string back_name = ".backup/" + lhs->filename; + fprintf(stderr, "[%s] -> [%s]\n", lhs->filename.c_str(), back_name.c_str()); + lhs->filename = back_name; + bkup_entries.push_back(std::move(lhs)); + } + + // Increment positions + if (res < 0) { + ++i; + } else if (res == 0) { + ++i; ++j; + } else { + ++j; } } - if (rem->filesize) - bak.push_back(rem); - else - delete rem; + if (!remv.empty()) { + auto rmlist = make_unique(".backup/.rmlist"); + rmlist->mode = S_IFREG; + rmlist->filesize = remv.length(); + rmlist->data = xmalloc(remv.length()); + memcpy(rmlist->data, remv.data(), remv.length()); + bkup_entries.push_back(std::move(rmlist)); + } - if (bak.size() > 1) - for (auto item : bak) - insert(item); + if (bkup_entries.size() > 1) { + entries.insert(entries.end(), + make_move_iterator(bkup_entries.begin()), make_move_iterator(bkup_entries.end())); + } } diff --git a/native/jni/utils/include/utils.h b/native/jni/utils/include/utils.h index 59eea0dfa..f8b056ca1 100644 --- a/native/jni/utils/include/utils.h +++ b/native/jni/utils/include/utils.h @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" {