diff --git a/native/jni/daemon/bootstages.cpp b/native/jni/daemon/bootstages.cpp index 019e50c6b..8c88e6ded 100644 --- a/native/jni/daemon/bootstages.cpp +++ b/native/jni/daemon/bootstages.cpp @@ -24,7 +24,7 @@ #include "flags.h" static char buf[PATH_MAX], buf2[PATH_MAX]; -static Array module_list; +static Array module_list; static int bind_mount(const char *from, const char *to); @@ -44,60 +44,62 @@ static int bind_mount(const char *from, const char *to); class node_entry { public: + node_entry(const char *, uint8_t status = 0, uint8_t type = 0); + ~node_entry(); + void create_module_tree(const char *module); + void magic_mount(); + node_entry *extract(const char *name); + +private: const char *module; /* Only used when status & IS_MODULE */ - char *name; + const CharArray name; uint8_t type; uint8_t status; node_entry *parent; Array children; - node_entry() = default; - node_entry(const char *, const char *, uint8_t type = 0, uint8_t status = 0); - node_entry(const char *, uint8_t type = 0, uint8_t status = 0); - ~node_entry(); - void create_module_tree(const char *module); - void magic_mount(); - -private: - char *get_path(); + node_entry(const char *, const char *, uint8_t type); + bool is_root(); + CharArray get_path(); node_entry *insert(node_entry *); void clone_skeleton(); int get_path(char *path); }; -node_entry::node_entry(const char *module, const char *name, uint8_t type, uint8_t status) - : node_entry(name, type, status) { +node_entry::node_entry(const char *name, uint8_t status, uint8_t type) + : name(name), type(type), status(status), parent(nullptr) {} + +node_entry::node_entry(const char *module, const char *name, uint8_t type) + : node_entry(name, (uint8_t) 0, type) { this->module = module; } -node_entry::node_entry(const char *name, uint8_t type, uint8_t status) - : type(type), status(status), parent(nullptr) { - this->name = strdup(name); -} - node_entry::~node_entry() { - free(name); for (auto &node : children) delete node; } -char *node_entry::get_path() { +bool node_entry::is_root() { + return parent == nullptr; +} + +CharArray node_entry::get_path() { get_path(buf); - return strdup(buf); + return buf; } int node_entry::get_path(char *path) { int len = 0; if (parent) len = parent->get_path(path); - len += sprintf(path + len, "/%s", name); + len += sprintf(path + len, "/%s", name.c_str()); return len; } node_entry *node_entry::insert(node_entry *node) { node->parent = this; for (auto &child : children) { - if (strcmp(child->name, node->name) == 0) { + if (child->name == node->name) { if (node->status > child->status) { // The new node has higher precedence delete child; @@ -117,18 +119,18 @@ void node_entry::create_module_tree(const char *module) { DIR *dir; struct dirent *entry; - char *full_path = get_path(); - snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, full_path); + CharArray full_path = get_path(); + snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, full_path.c_str()); if (!(dir = xopendir(buf))) - goto cleanup; + return; while ((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; // Create new node node_entry *node = new node_entry(module, entry->d_name, entry->d_type); - snprintf(buf, PATH_MAX, "%s/%s", full_path, node->name); + snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), entry->d_name); /* * Clone the parent in the following condition: @@ -139,7 +141,7 @@ void node_entry::create_module_tree(const char *module) { bool clone = false; if (IS_LNK(node) || access(buf, F_OK) == -1) { clone = true; - } else if (parent != nullptr || strcmp(node->name, "vendor") != 0) { + } else if (!is_root() || node->name != "vendor") { struct stat s; xstat(buf, &s); if (S_ISLNK(s.st_mode)) @@ -171,9 +173,6 @@ void node_entry::create_module_tree(const char *module) { } } closedir(dir); - -cleanup: - free(full_path); } void node_entry::clone_skeleton() { @@ -182,34 +181,29 @@ void node_entry::clone_skeleton() { struct node_entry *dummy; // Clone the structure - char *full_path = get_path(); - snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path); + CharArray full_path = get_path(); + snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path.c_str()); if (!(dir = xopendir(buf))) - goto cleanup; + return; while ((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; // Create dummy node - dummy = new node_entry(entry->d_name, entry->d_type, IS_DUMMY); + dummy = new node_entry(entry->d_name, IS_DUMMY, entry->d_type); insert(dummy); } closedir(dir); if (status & IS_SKEL) { - struct stat s; - char *con; - xstat(full_path, &s); - getfilecon(full_path, &con); - LOGI("mnt_tmpfs : %s\n", full_path); + file_attr attr; + getattr(full_path, &attr); + LOGI("mnt_tmpfs : %s\n", full_path.c_str()); xmount("tmpfs", full_path, "tmpfs", 0, nullptr); - chmod(full_path, s.st_mode & 0777); - chown(full_path, s.st_uid, s.st_gid); - setfilecon(full_path, con); - free(con); + setattr(full_path, &attr); } for (auto &child : children) { - snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name); + snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), child->name.c_str()); // Create the dummy file/directory if (IS_DIR(child)) @@ -218,50 +212,47 @@ void node_entry::clone_skeleton() { close(creat(buf, 0644)); // Links will be handled later - if (child->parent->parent == nullptr && strcmp(child->name, "vendor") == 0) { - if (IS_LNK(child)) { + if (is_root() && child->name == "vendor") { + if (seperate_vendor) { cp_afc(MIRRDIR "/system/vendor", "/system/vendor"); - LOGI("creat_link: %s <- %s\n", "/system/vendor", MIRRDIR "/system/vendor"); + LOGI("copy_link : %s <- %s\n", "/system/vendor", MIRRDIR "/system/vendor"); } // Skip continue; } else if (child->status & IS_MODULE) { // Mount from module file to dummy file - snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, child->module, full_path, child->name); + snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, + child->module, full_path.c_str(), child->name.c_str()); } else if (child->status & (IS_SKEL | IS_INTER)) { // It's an intermediate folder, recursive clone child->clone_skeleton(); continue; } else if (child->status & IS_DUMMY) { // Mount from mirror to dummy file - snprintf(buf2, PATH_MAX, "%s%s/%s", MIRRDIR, full_path, child->name); + snprintf(buf2, PATH_MAX, "%s%s/%s", MIRRDIR, full_path.c_str(), child->name.c_str()); } if (IS_LNK(child)) { // Copy symlinks directly cp_afc(buf2, buf); #ifdef MAGISK_DEBUG - LOGI("creat_link: %s <- %s\n",buf, buf2); + LOGI("copy_link : %s <- %s\n",buf, buf2); #else - LOGI("creat_link: %s\n", buf); + LOGI("copy_link : %s\n", buf); #endif } else { - snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name); + snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), child->name.c_str()); bind_mount(buf2, buf); } } - -cleanup: - free(full_path); } void node_entry::magic_mount() { if (status & IS_MODULE) { // Mount module item - char *real_path = get_path(); - snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, real_path); + CharArray real_path = get_path(); + snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, real_path.c_str()); bind_mount(buf, real_path); - free(real_path); } else if (status & IS_SKEL) { // The node is labeled to be cloned with skeleton, lets do it clone_skeleton(); @@ -274,6 +265,21 @@ void node_entry::magic_mount() { // There should be no dummies, so don't need to handle it here } +node_entry *node_entry::extract(const char *name) { + node_entry *node = nullptr; + // Extract the vendor node out of system tree and swap with placeholder + for (auto &child : children) { + if (child->name == name) { + node = child; + child = new node_entry(name); + child->parent = node->parent; + node->parent = nullptr; + break; + } + } + return node; +} + /*********** * setenvs * ***********/ @@ -320,7 +326,7 @@ static void exec_common_script(const char* stage) { } static void exec_module_script(const char* stage) { - for (auto &module : module_list) { + for (const char *module : module_list) { snprintf(buf2, PATH_MAX, "%s/%s/%s.sh", MOUNTPOINT, module, stage); snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, module); if (access(buf2, F_OK) == -1 || access(buf, F_OK) == 0) @@ -356,9 +362,9 @@ static void simple_mount(const char *path) { if (access(buf2, F_OK) == -1) continue; if (entry->d_type == DT_DIR) { - char *new_path = strdup(buf2); + char *new_path = strdup2(buf2); simple_mount(new_path); - free(new_path); + delete [] new_path; } else if (entry->d_type == DT_REG) { // Actual file path snprintf(buf, PATH_MAX, "%s%s", SIMPLEMOUNT, buf2); @@ -434,7 +440,7 @@ static int prepare_img() { snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, entry->d_name); if (access(buf, F_OK) == 0) continue; - module_list.push_back(strdup(entry->d_name)); + module_list.push_back(entry->d_name); } } closedir(dir); @@ -472,29 +478,22 @@ static void install_apk(const char *apk) { static bool check_data() { bool mnt = false; bool data = false; - Array mounts; + Array mounts; file_to_array("/proc/mounts", mounts); for (auto &line : mounts) { - if (strstr(line, " /data ") && strstr(line, "tmpfs") == nullptr) + if (line.contains(" /data ") && !line.contains("tmpfs")) mnt = true; - free(line); } - mounts.clear(); if (mnt) { - char *crypto = getprop("ro.crypto.state"); - if (crypto != nullptr) { - if (strcmp(crypto, "unencrypted") == 0) { + CharArray crypto = getprop("ro.crypto.state"); + if (!crypto.empty()) { + if (crypto == "unencrypted") { // Unencrypted, we can directly access data data = true; } else { // Encrypted, check whether vold is started - char *vold = getprop("init.svc.vold"); - if (vold != nullptr) { - free(vold); - data = true; - } + data = !getprop("init.svc.vold").empty(); } - free(crypto); } else { // ro.crypto.state is not set, assume it's unencrypted data = true; @@ -513,13 +512,12 @@ static void *start_magisk_hide(void *) { static void auto_start_magiskhide() { if (!start_log_daemon()) return; - char *hide_prop = getprop(MAGISKHIDE_PROP, 1); - if (hide_prop == nullptr || strcmp(hide_prop, "0") != 0) { + CharArray hide_prop = getprop(MAGISKHIDE_PROP, true); + if (hide_prop != "0") { pthread_t thread; xpthread_create(&thread, nullptr, start_magisk_hide, nullptr); pthread_detach(thread); } - free(hide_prop); } void unlock_blocks() { @@ -707,15 +705,14 @@ void startup() { xmkdir(BLOCKDIR, 0755); LOGI("* Mounting mirrors"); - Array mounts; + Array mounts; file_to_array("/proc/mounts", mounts); - int skip_initramfs = 0; - // Check whether skip_initramfs device + bool system_as_root = false; for (auto &line : mounts) { - if (strstr(line, " /system_root ")) { + if (line.contains(" /system_root ")) { bind_mount("/system_root/system", MIRRDIR "/system"); - skip_initramfs = 1; - } else if (!skip_initramfs && strstr(line, " /system ")) { + system_as_root = true; + } else if (!system_as_root && line.contains(" /system ")) { sscanf(line, "%s %*s %s", buf, buf2); xmount(buf, MIRRDIR "/system", buf2, MS_RDONLY, nullptr); #ifdef MAGISK_DEBUG @@ -723,7 +720,7 @@ void startup() { #else LOGI("mount: %s\n", MIRRDIR "/system"); #endif - } else if (strstr(line, " /vendor ")) { + } else if (line.contains(" /vendor ")) { seperate_vendor = 1; sscanf(line, "%s %*s %s", buf, buf2); xmkdir(MIRRDIR "/vendor", 0755); @@ -734,9 +731,7 @@ void startup() { LOGI("mount: %s\n", MIRRDIR "/vendor"); #endif } - free(line); } - mounts.clear(); if (!seperate_vendor) { xsymlink(MIRRDIR "/system/vendor", MIRRDIR "/vendor"); #ifdef MAGISK_DEBUG @@ -809,8 +804,7 @@ void post_fs_data(int client) { exec_module_script("post-fs-data"); // Create the system root entry - node_entry *sys_root = new node_entry("system"); - sys_root->status = IS_INTER; + node_entry *sys_root = new node_entry("system", IS_INTER); // Vendor root entry node_entry *ven_root = nullptr; @@ -818,7 +812,7 @@ void post_fs_data(int client) { bool has_modules = false; LOGI("* Loading modules\n"); - for (auto &module : module_list) { + for (const char *module : module_list) { // Read props snprintf(buf, PATH_MAX, "%s/%s/system.prop", MOUNTPOINT, module); if (access(buf, F_OK) == 0) { @@ -848,16 +842,8 @@ void post_fs_data(int client) { } if (has_modules) { - // Extract the vendor node out of system tree and swap with placeholder - for (auto &child : sys_root->children) { - if (strcmp(child->name, "vendor") == 0) { - ven_root = child; - child = new node_entry("vendor", seperate_vendor ? DT_LNK : DT_DIR); - child->parent = ven_root->parent; - ven_root->parent = nullptr; - break; - } - } + // Pull out /system/vendor node if exist + ven_root = sys_root->extract("vendor"); // Magic!! sys_root->magic_mount(); @@ -866,7 +852,7 @@ void post_fs_data(int client) { // Cleanup memory delete sys_root; - if (ven_root) delete ven_root; + delete ven_root; core_only(); } @@ -922,9 +908,7 @@ core_only: } // All boot stage done, cleanup - for (auto &module : module_list) - free(module); - module_list.clear(); + module_list.clear(true); } void boot_complete(int client) { diff --git a/native/jni/daemon/daemon.cpp b/native/jni/daemon/daemon.cpp index e3e9c50a5..3f72be6bd 100644 --- a/native/jni/daemon/daemon.cpp +++ b/native/jni/daemon/daemon.cpp @@ -82,7 +82,7 @@ static void *request_handler(void *args) { close(client); break; } - return NULL; + return nullptr; } static void main_daemon() { diff --git a/native/jni/include/resetprop.h b/native/jni/include/resetprop.h index eaad8733f..fbd01dc22 100644 --- a/native/jni/include/resetprop.h +++ b/native/jni/include/resetprop.h @@ -3,9 +3,11 @@ #pragma once +#include "CharArray.h" + int prop_exist(const char *name); int setprop(const char *name, const char *value, const bool trigger = true); -char *getprop(const char *name, bool persist = false); +CharArray getprop(const char *name, bool persist = false); void getprop(void (*callback)(const char *, const char *, void *), void *cookie, bool persist = false); int deleteprop(const char *name, bool persist = false); int load_prop_file(const char *filename, const bool trigger = true); diff --git a/native/jni/magiskboot/cpio.cpp b/native/jni/magiskboot/cpio.cpp index 0b153ef6d..183bdb51b 100644 --- a/native/jni/magiskboot/cpio.cpp +++ b/native/jni/magiskboot/cpio.cpp @@ -40,8 +40,8 @@ cpio_entry::cpio_entry(int fd, cpio_newc_header &header) { // rdevminor = x8u(header.rdevminor); uint32_t namesize = x8u(header.namesize); // check = x8u(header.check); - filename = (char *) xmalloc(namesize); - xxread(fd, filename, namesize); + filename = CharArray(namesize); + xxread(fd, filename, filename.size()); parse_align(); if (filesize) { data = xmalloc(filesize); @@ -51,7 +51,6 @@ cpio_entry::cpio_entry(int fd, cpio_newc_header &header) { } cpio_entry::~cpio_entry() { - free(filename); free(data); } @@ -61,7 +60,7 @@ int(*Array::_cmp)(cpio_entry*&, cpio_entry*&) = [](auto a, auto b) if (a == b) return 0; if (a == nullptr) return 1; if (b == nullptr) return -1; - return strcmp(a->filename, b->filename); + return a->filename.compare(b->filename); }; @@ -73,12 +72,11 @@ cpio::cpio(const char *filename) { cpio_entry *entry; while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) { entry = new cpio_entry(fd, header); - if (strcmp(entry->filename, ".") == 0 || strcmp(entry->filename, "..") == 0 || - strcmp(entry->filename, "TRAILER!!!") == 0) { + if (entry->filename == "." || entry->filename == ".." || entry->filename == "TRAILER!!!") { + bool trailer = entry->filename[0] == 'T'; delete entry; - if (entry->filename[0] == 'T') + if (trailer) break; - continue; } arr.push_back(entry); } @@ -110,11 +108,11 @@ void cpio::dump(const char *file) { 0, // e->devminor 0, // e->rdevmajor 0, // e->rdevminor - (uint32_t) strlen(e->filename) + 1, + (uint32_t) e->filename.size(), 0 // e->check ); xwrite(fd, header, 110); - xwrite(fd, e->filename, strlen(e->filename) + 1); + xwrite(fd, e->filename, e->filename.size()); dump_align(); if (e->filesize) { xwrite(fd, e->data, e->filesize); @@ -134,7 +132,7 @@ int cpio::find(const char *name) { for (int i = 0; i < arr.size(); ++i) { if (!arr[i]) continue; - if (strcmp(arr[i]->filename, name) == 0) + if (arr[i]->filename == name) return i; } return -1; @@ -143,12 +141,11 @@ int cpio::find(const char *name) { void cpio::insert(cpio_entry *e) { int i = find(e->filename); if (i >= 0) { - // Replace, then all is done delete arr[i]; arr[i] = e; - return; + } else { + arr.push_back(e); } - arr.push_back(e); } void cpio::insert(Array &arr) { @@ -156,17 +153,17 @@ void cpio::insert(Array &arr) { insert(e); } -void cpio::rm(int recur, const char *name) { +void cpio::rm(const char *name, bool r) { size_t len = strlen(name); for (auto &e : arr) { if (!e) continue; - if (strncmp(e->filename, name, len) == 0 && - ((recur && e->filename[len] == '/') || e->filename[len] == '\0')) { - fprintf(stderr, "Remove [%s]\n", e->filename); + if (e->filename.compare(name, len) == 0 && + ((r && e->filename[len] == '/') || e->filename[len] == '\0')) { + fprintf(stderr, "Remove [%s]\n", e->filename.c_str()); delete e; e = nullptr; - if (!recur) + if (!r) return; } } @@ -175,7 +172,7 @@ void cpio::rm(int recur, const char *name) { void cpio::makedir(mode_t mode, const char *name) { auto e = new cpio_entry(); e->mode = S_IFDIR | mode; - e->filename = strdup(name); + e->filename = name; insert(e); fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode); } @@ -183,7 +180,7 @@ void cpio::makedir(mode_t mode, const char *name) { void cpio::ln(const char *target, const char *name) { auto e = new cpio_entry(); e->mode = S_IFLNK; - e->filename = strdup(name); + e->filename = name; e->filesize = strlen(target); e->data = strdup(target); insert(e); @@ -194,7 +191,7 @@ void cpio::add(mode_t mode, const char *name, const char *file) { int fd = xopen(file, O_RDONLY); auto e = new cpio_entry(); e->mode = S_IFREG | mode; - e->filename = strdup(name); + e->filename = name; e->filesize = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); e->data = xmalloc(e->filesize); @@ -212,35 +209,38 @@ bool cpio::mv(const char *from, const char *to) { arr[t] = nullptr; } fprintf(stderr, "Move [%s] -> [%s]\n", from, to); - char * tmp = strdup(to); - free(arr[f]->filename); - arr[f]->filename = tmp; + arr[f]->filename = to; return true; } fprintf(stderr, "Cannot find entry %s\n", from); return false; } +static void extract_entry(cpio_entry *e, const char *file) { + fprintf(stderr, "Extract [%s] to [%s]\n", e->filename.c_str(), file); + unlink(file); + rmdir(file); + if (S_ISDIR(e->mode)) { + mkdir(file, e->mode & 0777); + } else if (S_ISREG(e->mode)) { + int fd = creat(file, e->mode & 0777); + xwrite(fd, e->data, e->filesize); + fchown(fd, e->uid, e->gid); + close(fd); + } else if (S_ISLNK(e->mode)) { + auto target = new char[e->filesize + 1]; + memcpy(target, e->data, e->filesize); + target[e->filesize] = '\0'; + symlink(target, file); + delete[] target; + } +} + void cpio::extract() { for (auto &e : arr) { if (!e) continue; - fprintf(stderr, "Extract [%s]\n", e->filename); - unlink(e->filename); - rmdir(e->filename); - if (S_ISDIR(e->mode)) { - mkdir(e->filename, e->mode & 0777); - } else if (S_ISREG(e->mode)) { - int fd = creat(e->filename, e->mode & 0777); - xwrite(fd, e->data, e->filesize); - fchown(fd, e->uid, e->gid); - close(fd); - } else if (S_ISLNK(e->mode)) { - char *target = new char[e->filesize + 1]; - memcpy(target, e->data, e->filesize); - symlink(target, e->filename); - delete[] target; - } + extract_entry(e, e->filename); } } @@ -248,18 +248,7 @@ bool cpio::extract(const char *name, const char *file) { int i = find(name); if (i > 0) { auto e = arr[i]; - fprintf(stderr, "Extract [%s] to [%s]\n", name, file); - if (S_ISREG(e->mode)) { - int fd = creat(file, e->mode & 0777); - xwrite(fd, e->data, e->filesize); - fchown(fd, e->uid, e->gid); - close(fd); - } else if (S_ISLNK(e->mode)) { - char *target = new char[e->filesize + 1]; - memcpy(target, e->data, e->filesize); - symlink(target, e->filename); - delete[] target; - } + extract_entry(e, file); return true; } fprintf(stderr, "Cannot find the file entry [%s]\n", name); diff --git a/native/jni/magiskboot/cpio.h b/native/jni/magiskboot/cpio.h index 9a2e6472e..fee9f200d 100644 --- a/native/jni/magiskboot/cpio.h +++ b/native/jni/magiskboot/cpio.h @@ -4,6 +4,7 @@ #include #include "array.h" +#include "CharArray.h" struct cpio_newc_header { char magic[6]; @@ -36,7 +37,8 @@ struct cpio_entry { // uint32_t rdevminor; // uint32_t namesize; // uint32_t check; - char *filename = nullptr; +// char *filename = nullptr; + CharArray filename; void *data = nullptr; cpio_entry() {} @@ -51,7 +53,7 @@ public: void dump(const char *file); int find(const char *name); void insert(cpio_entry *e); - void rm(int recur, const char *name); + void rm(const char *name, bool r = false); void makedir(mode_t mode, const char *name); void ln(const char *target, const char *name); void add(mode_t mode, const char *name, const char *file); diff --git a/native/jni/magiskboot/ramdisk.cpp b/native/jni/magiskboot/ramdisk.cpp index 40218d30c..07533862d 100644 --- a/native/jni/magiskboot/ramdisk.cpp +++ b/native/jni/magiskboot/ramdisk.cpp @@ -23,10 +23,13 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { for (auto &e : arr) { if (!e) continue; + bool fstab = (!keepverity || !keepforceencrypt) && + !e->filename.starts_with(".backup") && + e->filename.contains("fstab") && S_ISREG(e->mode); if (!keepverity) { - if (strncmp(e->filename, ".backup", 7) && strstr(e->filename, "fstab") && S_ISREG(e->mode)) { + if (fstab) { patch_verity(&e->data, &e->filesize, 1); - } else if (strcmp(e->filename, "verity_key") == 0) { + } else if (e->filename == "verity_key") { fprintf(stderr, "Remove [verity_key]\n"); delete e; e = nullptr; @@ -34,7 +37,7 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { } } if (!keepforceencrypt) { - if (strstr(e->filename, "fstab") != NULL && S_ISREG(e->mode)) { + if (fstab) { patch_encryption(&e->data, &e->filesize); } } @@ -47,27 +50,26 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { #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", nullptr }; + "boot/sbin/launch_daemonsu.sh" }; static const char *MAGISK_LIST[] = { ".backup/.magisk", "init.magisk.rc", - "overlay/init.magisk.rc", nullptr }; + "overlay/init.magisk.rc" }; - for (int i = 0; UNSUPPORT_LIST[i]; ++i) - if (find(UNSUPPORT_LIST[i]) >= 0) + for (auto file : UNSUPPORT_LIST) + if (find(file) >= 0) return UNSUPPORT_PATCH; - for (int i = 0; MAGISK_LIST[i]; ++i) - if (find(MAGISK_LIST[i]) >= 0) + for (auto file : MAGISK_LIST) + if (find(file) >= 0) return MAGISK_PATCH; return STOCK_BOOT; } -char * magisk_cpio::sha1() { +char *magisk_cpio::sha1() { char sha1[41]; for (auto &e : arr) { if (!e) continue; - if (strcmp(e->filename, "init.magisk.rc") == 0 - || strcmp(e->filename, "overlay/init.magisk.rc") == 0) { + if (e->filename == "init.magisk.rc" || e->filename == "overlay/init.magisk.rc") { for (char *pos = (char *) e->data; pos < (char *) e->data + e->filesize; pos = strchr(pos + 1, '\n') + 1) { if (memcmp(pos, "# STOCKSHA1=", 12) == 0) { @@ -77,7 +79,7 @@ char * magisk_cpio::sha1() { return strdup(sha1); } } - } else if (strcmp(e->filename, ".backup/.sha1") == 0) { + } else if (e->filename == ".backup/.sha1") { return (char *) e->data; } } @@ -87,12 +89,12 @@ char * magisk_cpio::sha1() { void magisk_cpio::restore() { for (auto &e : arr) { if (!e) continue; - if (strncmp(e->filename, ".backup", 7) == 0) { + if (e->filename.starts_with(".backup")) { if (e->filename[7] == '\0') continue; if (e->filename[8] == '.') { - if (strcmp(e->filename + 8, ".rmlist") == 0) { + if (strcmp(&e->filename[8], ".rmlist") == 0) { for (int pos = 0; pos < e->filesize; pos += strlen((char *) e->data + pos) + 1) - rm(false, (char *) e->data + pos); + rm((char *) e->data + pos, false); } } else { mv(e->filename, e->filename + 8); @@ -101,43 +103,41 @@ void magisk_cpio::restore() { } // Some known stuff we can remove - rm(true, ".backup"); - rm(true, "overlay"); - rm(false, "sbin/magic_mask.sh"); - rm(false, "init.magisk.rc"); - rm(true, "magisk"); + rm(".backup", true); + rm("overlay", true); + rm("sbin/magic_mask.sh", false); + rm("init.magisk.rc", false); + rm("magisk", true); } void magisk_cpio::backup(Array &bak, const char *orig, const char *sha1) { cpio_entry *m, *n, *rem, *cksm; char buf[PATH_MAX]; - int res; - bool backup; m = new cpio_entry(); - m->filename = strdup(".backup"); + m->filename = ".backup"; m->mode = S_IFDIR; bak.push_back(m); rem = new cpio_entry(); - rem->filename = strdup(".backup/.rmlist"); + rem->filename = ".backup/.rmlist"; rem->mode = S_IFREG; if (sha1) { fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1); cksm = new cpio_entry(); - bak.push_back(cksm); - cksm->filename = strdup(".backup/.sha1"); + cksm->filename = ".backup/.sha1"; cksm->mode = S_IFREG; cksm->data = strdup(sha1); cksm->filesize = strlen(sha1) + 1; + bak.push_back(cksm); } - magisk_cpio o = magisk_cpio(orig); + magisk_cpio o(orig); // Remove possible backups in original ramdisk - o.rm(true, ".backup"); - rm(true, ".backup"); + o.rm(".backup", true); + rm(".backup", true); // Sort both CPIOs before comparing o.sort(); @@ -146,11 +146,12 @@ void magisk_cpio::backup(Array &bak, const char *orig, const char * // Start comparing size_t i = 0, j = 0; while(i != o.arr.size() || j != arr.size()) { - backup = false; + int res; + bool backup = false; if (i != o.arr.size() && j != arr.size()) { m = o.arr[i]; n = arr[j]; - res = strcmp(m->filename, n->filename); + res = m->filename.compare(n->filename); } else if (i == o.arr.size()) { n = arr[j]; res = 1; @@ -174,16 +175,15 @@ void magisk_cpio::backup(Array &bak, const char *orig, const char * } else { // Something new in ramdisk, record in rem ++j; - rem->data = xrealloc(rem->data, rem->filesize + strlen(n->filename) + 1); - memcpy((char *) rem->data + rem->filesize, n->filename, strlen(n->filename) + 1); - rem->filesize += strlen(n->filename) + 1; - fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename); + rem->data = xrealloc(rem->data, rem->filesize + n->filename.size()); + memcpy((char *) rem->data + rem->filesize, n->filename, n->filename.size()); + rem->filesize += n->filename.size(); + fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename.c_str()); } if (backup) { - sprintf(buf, ".backup/%s", m->filename); - fprintf(stderr, "[%s] -> [%s]\n", m->filename, buf); - free(m->filename); - m->filename = strdup(buf); + 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; @@ -202,7 +202,7 @@ int cpio_commands(int argc, char *argv[]) { ++argv; --argc; - magisk_cpio cpio = magisk_cpio(incpio); + magisk_cpio cpio(incpio); int cmdc; char *cmdv[6]; @@ -230,17 +230,17 @@ int cpio_commands(int argc, char *argv[]) { free(sha1); return 0; } else if (cmdc >= 2 && strcmp(cmdv[0], "backup") == 0) { - auto bak = Array(); + Array bak; cpio.backup(bak, cmdv[1], cmdv[2]); cpio.insert(bak); } else if (cmdc >= 4 && strcmp(cmdv[0], "magisk") == 0) { cpio.patch(strcmp(cmdv[2], "true") == 0, strcmp(cmdv[3], "true") == 0); - auto bak = Array(); + Array bak; cpio.backup(bak, cmdv[1], cmdv[4]); auto e = new cpio_entry(); - e->filename = strdup(".backup/.magisk"); + e->filename = ".backup/.magisk"; e->mode = S_IFREG; e->data = xmalloc(50); snprintf((char *) e->data, 50, "KEEPVERITY=%s\nKEEPFORCEENCRYPT=%s\n", cmdv[2], cmdv[3]); @@ -249,8 +249,8 @@ int cpio_commands(int argc, char *argv[]) { cpio.insert(bak); cpio.insert(e); } else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) { - int recur = cmdc > 2 && strcmp(cmdv[1], "-r") == 0; - cpio.rm(recur, cmdv[1 + recur]); + bool r = cmdc > 2 && strcmp(cmdv[1], "-r") == 0; + cpio.rm(cmdv[1 + r], r); } else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) { cpio.mv(cmdv[1], cmdv[2]); } else if (cmdc == 3 && strcmp(cmdv[0], "patch") == 0) { diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index 734390a62..fd6c05b83 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -15,7 +15,7 @@ #include "daemon.h" #include "db.h" -auto hide_list = Array(); +Array hide_list; static const char *prop_key[] = { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", @@ -46,14 +46,10 @@ void hide_sensitive_props() { LOGI("hide_utils: Hiding sensitive props\n"); // Hide all sensitive props - char *value; for (int i = 0; prop_key[i]; ++i) { - value = getprop(prop_key[i]); - if (value) { - if (strcmp(value, prop_value[i]) != 0) - setprop(prop_key[i], prop_value[i], false); - free(value); - } + CharArray value = getprop(prop_key[i]); + if (!value.empty() && value != prop_value[i]) + setprop(prop_key[i], prop_value[i], false); } } @@ -139,13 +135,11 @@ void clean_magisk_props() { }, nullptr, false); } -static int add_list(sqlite3 *db, char *proc) { +static int add_list(sqlite3 *db, const char *proc) { for (auto &s : hide_list) { // They should be unique - if (strcmp(s, proc) == 0) { - free(proc); + if (s == proc) return HIDE_ITEM_EXIST; - } } LOGI("hide_list add: [%s]\n", proc); @@ -164,7 +158,7 @@ static int add_list(sqlite3 *db, char *proc) { return DAEMON_SUCCESS; } -int add_list(char *proc) { +int add_list(const char *proc) { sqlite3 *db = get_magiskdb(); if (db) { int ret = add_list(db, proc); @@ -175,20 +169,20 @@ int add_list(char *proc) { } int add_list(int client) { - return add_list(read_string(client)); + char *proc = read_string(client); + int ret = add_list(proc); + free(proc); + return ret; } -static int rm_list(char *proc) { - int ret = DAEMON_ERROR; - +static int rm_list(const char *proc) { // Update list in critical region bool do_rm = false; pthread_mutex_lock(&list_lock); for (auto it = hide_list.begin(); it != hide_list.end(); ++it) { - if (strcmp(*it, proc) == 0) { + if (*it == proc) { do_rm = true; LOGI("hide_list rm: [%s]\n", proc); - free(*it); hide_list.erase(it); break; } @@ -199,45 +193,44 @@ static int rm_list(char *proc) { kill_process(proc); sqlite3 *db = get_magiskdb(); if (db == nullptr) - goto error; + return DAEMON_ERROR; char sql[128]; sprintf(sql, "DELETE FROM hidelist WHERE process='%s'", proc); sqlite3_exec(db, sql, nullptr, nullptr, nullptr); sqlite3_close_v2(db); - ret = DAEMON_SUCCESS; + return DAEMON_SUCCESS; } else { - ret = HIDE_ITEM_NOT_EXIST; + return HIDE_ITEM_NOT_EXIST; } +} -error: +int rm_list(int client) { + char *proc = read_string(client); + int ret = rm_list(proc); free(proc); return ret; } -int rm_list(int client) { - return rm_list(read_string(client)); -} - #define LEGACY_LIST MOUNTPOINT "/.core/hidelist" -int init_list() { +bool init_list() { LOGD("hide_list: initialize\n"); sqlite3 *db = get_magiskdb(); if (db == nullptr) - return 1; + return false; sqlite3_exec(db, "SELECT process FROM hidelist", [] (auto, auto, char **data, auto) -> int { LOGI("hide_list: [%s]\n", data[0]); - hide_list.push_back(strdup(data[0])); + hide_list.push_back(data[0]); return 0; }, nullptr, nullptr); // Migrate old hide list into database if (access(LEGACY_LIST, R_OK) == 0) { - auto tmp = Array(); + Array tmp; file_to_array(LEGACY_LIST, tmp); for (auto &s : tmp) add_list(db, s); @@ -245,14 +238,7 @@ int init_list() { } sqlite3_close_v2(db); - return 0; -} - -int destroy_list() { - for (auto &str : hide_list) - free(str); - hide_list.clear(); - return 0; + return true; } void ls_list(int client) { diff --git a/native/jni/magiskhide/magiskhide.cpp b/native/jni/magiskhide/magiskhide.cpp index 4b55ba1f2..6dce20a80 100644 --- a/native/jni/magiskhide/magiskhide.cpp +++ b/native/jni/magiskhide/magiskhide.cpp @@ -54,11 +54,11 @@ int launch_magiskhide() { pthread_mutex_init(&list_lock, nullptr); // Initialize the hide list - if (init_list()) + if (!init_list()) goto error; // Add SafetyNet by default - add_list(strdup("com.google.android.gms.unstable")); + add_list("com.google.android.gms.unstable"); // Get thread reference proc_monitor_thread = pthread_self(); diff --git a/native/jni/magiskhide/magiskhide.h b/native/jni/magiskhide/magiskhide.h index 288776818..af2c0f7dc 100644 --- a/native/jni/magiskhide/magiskhide.h +++ b/native/jni/magiskhide/magiskhide.h @@ -5,6 +5,7 @@ #include "daemon.h" #include "array.h" +#include "CharArray.h" #define TERM_THREAD SIGUSR1 @@ -24,13 +25,12 @@ void hide_sensitive_props(); void clean_magisk_props(); // List managements -int add_list(char *proc); -int init_list(); -int destroy_list(); +int add_list(const char *proc); +bool init_list(); extern int hide_enabled; extern pthread_mutex_t list_lock; -extern Array hide_list; +extern Array hide_list; enum { LAUNCH_MAGISKHIDE, diff --git a/native/jni/magiskhide/proc_monitor.cpp b/native/jni/magiskhide/proc_monitor.cpp index 447bda029..0f72ee972 100644 --- a/native/jni/magiskhide/proc_monitor.cpp +++ b/native/jni/magiskhide/proc_monitor.cpp @@ -27,13 +27,13 @@ static int sockfd = -1; // Workaround for the lack of pthread_cancel static void term_thread(int) { LOGD("proc_monitor: running cleanup\n"); - destroy_list(); + hide_list.clear(true); hide_enabled = 0; close(sockfd); sockfd = -1; pthread_mutex_destroy(&list_lock); LOGD("proc_monitor: terminating\n"); - pthread_exit(NULL); + pthread_exit(nullptr); } static int read_ns(const int pid, struct stat *st) { @@ -63,7 +63,7 @@ static void hide_daemon(int pid) { LOGD("hide_daemon: start unmount for pid=[%d]\n", pid); char buffer[PATH_MAX]; - auto mounts = Array(); + Array mounts; manage_selinux(); clean_magisk_props(); @@ -76,11 +76,10 @@ static void hide_daemon(int pid) { // Unmount dummy skeletons and /sbin links for (auto &s : mounts) { - if (strstr(s, "tmpfs /system/") || strstr(s, "tmpfs /vendor/") || strstr(s, "tmpfs /sbin")) { + if (s.contains("tmpfs /system/") || s.contains("tmpfs /vendor/") || s.contains("tmpfs /sbin")) { sscanf(s, "%*s %4096s", buffer); lazy_unmount(buffer); } - free(s); } mounts.clear(); @@ -90,13 +89,11 @@ static void hide_daemon(int pid) { // Unmount everything under /system, /vendor, and loop mounts for (auto &s : mounts) { - if (strstr(s, "/dev/block/loop") || strstr(s, " /system/") || strstr(s, " /vendor/")) { + if (s.contains("/dev/block/loop") || s.contains(" /system/") || s.contains(" /vendor/")) { sscanf(s, "%*s %4096s", buffer); lazy_unmount(buffer); } - free(s); } - mounts.clear(); exit: // Send resume signal @@ -159,7 +156,7 @@ void proc_monitor() { bool hide = false; pthread_mutex_lock(&list_lock); for (auto &s : hide_list) { - if (strcmp(proc, s) == 0) { + if (s == proc) { hide = true; break; } diff --git a/native/jni/resetprop/_resetprop.h b/native/jni/resetprop/_resetprop.h index 2ef3aef92..3a693b993 100644 --- a/native/jni/resetprop/_resetprop.h +++ b/native/jni/resetprop/_resetprop.h @@ -5,6 +5,7 @@ #ifndef MAGISK_PROPS_H #define MAGISK_PROPS_H +#include #include "resetprop/private/system_properties.h" #include "logging.h" @@ -48,7 +49,7 @@ struct read_cb_t { extern bool use_pb; -char *persist_getprop(const char *name); +CharArray persist_getprop(const char *name); void persist_getprop(read_cb_t *read_cb); bool persist_deleteprop(const char *name); void collect_props(const char *name, const char *value, void *v_plist); diff --git a/native/jni/resetprop/persist_properties.cpp b/native/jni/resetprop/persist_properties.cpp index 60164c283..701ffef37 100644 --- a/native/jni/resetprop/persist_properties.cpp +++ b/native/jni/resetprop/persist_properties.cpp @@ -190,21 +190,21 @@ void persist_getprop(read_cb_t *read_cb) { } } -char *persist_getprop(const char *name) { +CharArray persist_getprop(const char *name) { prop_t prop(name); if (use_pb) { read_cb_t read_cb(pb_getprop_cb, &prop); pb_getprop(&read_cb); if (prop.value[0]) - return strdup(prop.value); + return prop.value; } else { // Try to read from file char value[PROP_VALUE_MAX]; file_getprop(name, value); if (value[0]) - return strdup(value); + return value; } - return nullptr; + return CharArray(); } bool persist_deleteprop(const char *name) { diff --git a/native/jni/resetprop/resetprop.cpp b/native/jni/resetprop/resetprop.cpp index 466b3cac9..d181f3e11 100644 --- a/native/jni/resetprop/resetprop.cpp +++ b/native/jni/resetprop/resetprop.cpp @@ -130,18 +130,18 @@ int prop_exist(const char *name) { } // Get prop by name, return string (should free manually!) -char *getprop(const char *name, bool persist) { +CharArray getprop(const char *name, bool persist) { if (!check_legal_property_name(name) || init_resetprop()) return nullptr; const prop_info *pi = __system_property_find(name); if (pi == nullptr) { if (persist && strncmp(name, "persist.", 8) == 0) { - char *value = persist_getprop(name); - if (value) + CharArray value = persist_getprop(name); + if (!value.empty()) return value; } LOGD("resetprop: prop [%s] does not exist\n", name); - return nullptr; + return CharArray(); } else { char value[PROP_VALUE_MAX]; read_cb_t read_cb; @@ -149,7 +149,7 @@ char *getprop(const char *name, bool persist) { read_cb.arg = value; read_props(pi, &read_cb); LOGD("resetprop: getprop [%s]: [%s]\n", name, value); - return strdup(value); + return value; } } @@ -254,7 +254,8 @@ int resetprop_main(int argc, char *argv[]) { log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; }; bool trigger = true, persist = false; - char *argv0 = argv[0], *prop; + char *argv0 = argv[0]; + CharArray prop; --argc; ++argv; @@ -297,10 +298,9 @@ int resetprop_main(int argc, char *argv[]) { print_props(persist); return 0; case 1: - prop = getprop(argv[0], persist); - if (prop == nullptr) return 1; - printf("%s\n", prop); - free(prop); + prop = utils::move(getprop(argv[0], persist)); + if (!prop) return 1; + printf("%s\n", prop.c_str()); return 0; case 2: return setprop(argv[0], argv[1], trigger); diff --git a/native/jni/utils/Android.mk b/native/jni/utils/Android.mk index 55d56c734..5a60c3d31 100644 --- a/native/jni/utils/Android.mk +++ b/native/jni/utils/Android.mk @@ -9,6 +9,7 @@ LOCAL_SRC_FILES := \ selinux.cpp \ logging.cpp \ xwrap.cpp \ + CharArray.cpp \ vector.c include $(BUILD_STATIC_LIBRARY) diff --git a/native/jni/utils/CharArray.cpp b/native/jni/utils/CharArray.cpp new file mode 100644 index 000000000..fb67883c9 --- /dev/null +++ b/native/jni/utils/CharArray.cpp @@ -0,0 +1,99 @@ +#include "CharArray.h" +#include "utils.h" + +CharArray::CharArray() : _buf(nullptr), _size(0){} + +CharArray::CharArray(const char *s) : CharArray() { + this->operator=(s); +} + +CharArray::CharArray(const CharArray &s) : CharArray() { + this->operator=(s); +} + +CharArray::CharArray(size_t i) { + _size = i; + _buf = new char[i](); /* Zero initialize */ +} + +CharArray::~CharArray() { + delete[] _buf; +} + +CharArray::operator char *() { + return _buf; +} + +CharArray::operator const char *() const { + return _buf; +} + +const char *CharArray::c_str() const { + return _buf; +} + +size_t CharArray::length() const { + return strlen(_buf); +} + +size_t CharArray::size() const { + return _size; +} + +CharArray &CharArray::operator=(const CharArray &s) { + delete[] _buf; + _size = s._size; + _buf = new char[_size]; + memcpy(_buf, s._buf, _size); + return *this; +} + +CharArray &CharArray::operator=(const char *s) { + delete[] _buf; + _buf = strdup2(s, &_size); + return *this; +} + +CharArray &CharArray::operator=(CharArray &&s) { + delete[] _buf; + _size = s._size; + _buf = s._buf; + s._buf = nullptr; + s._size = 0; + return *this; +} + +bool CharArray::operator==(const char *s) const { + if (_buf == nullptr || s == nullptr) + return false; + return strcmp(_buf, s) == 0; +} + +bool CharArray::operator==(char *s) const { + return *this == (const char *) s; +} + +bool CharArray::operator!=(const char *s) const { + return !(*this == s); +} + +int CharArray::compare(const char *s) const { + return strcmp(_buf, s); +} + +int CharArray::compare(const char *s, size_t len) const { + return strncmp(_buf, s, len); +} + +bool CharArray::contains(const char *s) const { + return strstr(_buf, s) != nullptr; +} + +bool CharArray::starts_with(const char *s) const { + return compare(s, strlen(s)) == 0; +} + +bool CharArray::empty() const { + return _buf == nullptr || _buf[0] == '\0'; +} + diff --git a/native/jni/utils/file.cpp b/native/jni/utils/file.cpp index 715350e6e..eb32a130a 100644 --- a/native/jni/utils/file.cpp +++ b/native/jni/utils/file.cpp @@ -388,7 +388,7 @@ void write_zero(int fd, size_t size) { lseek(fd, pos + size, SEEK_SET); } -int file_to_array(const char *filename, Array &arr) { +int file_to_array(const char *filename, Array &arr) { if (access(filename, R_OK) != 0) return 1; char *line = nullptr; @@ -404,8 +404,8 @@ int file_to_array(const char *filename, Array &arr) { if (line[read - 1] == '\n') line[read - 1] = '\0'; arr.push_back(line); - line = nullptr; } fclose(fp); + free(line); return 0; } diff --git a/native/jni/utils/include/CharArray.h b/native/jni/utils/include/CharArray.h new file mode 100644 index 000000000..6514df9fb --- /dev/null +++ b/native/jni/utils/include/CharArray.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +/* A wrapper around char array */ +class CharArray { +public: + CharArray(); + CharArray(const char *s); + CharArray(const CharArray &s); + CharArray(size_t i); + ~CharArray(); + + CharArray &operator=(const CharArray &s); + CharArray &operator=(CharArray &&s); + CharArray &operator=(const char *s); + + operator char *(); + operator const char *() const; + bool operator==(char *s) const; + bool operator==(const char *s) const; + bool operator!=(const char *s) const; + int compare(const char *s) const; + int compare(const char *s, size_t len) const; + bool starts_with(const char *s) const; + bool contains(const char *s) const; + bool empty() const; + const char *c_str() const; + size_t length() const; + size_t size() const; + + /* These 2 ops are incompatible with implicit char* conversion */ +// char &operator[](size_t i); +// const char &operator[](size_t i) const; + +private: + char *_buf; + size_t _size; +}; diff --git a/native/jni/utils/include/array.h b/native/jni/utils/include/array.h index 5d83defeb..2e59c1e16 100644 --- a/native/jni/utils/include/array.h +++ b/native/jni/utils/include/array.h @@ -1,6 +1,7 @@ #pragma once #include +#include "cpputils.h" template class Array { @@ -72,7 +73,7 @@ public: if (_capacity) { _data = new T[_capacity]; for(int i = 0; i < _size; ++i) - _data[i] = (T&&) a[i]; + _data[i] = utils::move(a[i]); } return *this; } @@ -101,7 +102,7 @@ public: void push_back(T&& x) { if(_size == _capacity) expand(); - _data[_size] = (T&&) x; + _data[_size] = utils::move(x); ++_size; } @@ -114,7 +115,7 @@ public: if (_size == 0 || d < _data || d >= _data + _size) return false; for (; d < _data + _size - 1; ++d) - *d = (T&&) *(d + 1); + *d = utils::move(*(d + 1)); --_size; return true; @@ -130,9 +131,16 @@ public: return false; } - void clear() { _size = 0; } + void clear(bool dealloc = false) { + _size = 0; + if (dealloc) { + _capacity = 0; + delete [] _data; + _data = nullptr; + } + } - void sort() const { + void sort() { qsort(_data, _size, sizeof(T), compare); } @@ -161,7 +169,7 @@ private: T* temp = _data; _data = new T[_capacity]; for(int i = 0; i < _size; ++i) - _data[i] = (T&&) temp[i]; + _data[i] = utils::move(temp[i]); delete [] temp; } }; diff --git a/native/jni/utils/include/cpputils.h b/native/jni/utils/include/cpputils.h new file mode 100644 index 000000000..d16706c01 --- /dev/null +++ b/native/jni/utils/include/cpputils.h @@ -0,0 +1,12 @@ +#pragma once + +namespace utils { + template< class T > struct remove_reference {typedef T type;}; + template< class T > struct remove_reference {typedef T type;}; + template< class T > struct remove_reference {typedef T type;}; + + template< class T > + constexpr typename remove_reference::type&& move( T&& t ) noexcept { + return static_cast::type&&>(t); + } +} \ No newline at end of file diff --git a/native/jni/utils/include/utils.h b/native/jni/utils/include/utils.h index c9f4aaed8..7b4b37ac0 100644 --- a/native/jni/utils/include/utils.h +++ b/native/jni/utils/include/utils.h @@ -12,9 +12,15 @@ #include #ifdef __cplusplus -// C++ only + #include "array.h" -int file_to_array(const char* filename, Array &arr); +#include "CharArray.h" +#include "cpputils.h" + +int file_to_array(const char *filename, Array &arr); +char *strdup2(const char *s, size_t *size = nullptr); + + extern "C" { #endif diff --git a/native/jni/utils/misc.cpp b/native/jni/utils/misc.cpp index 50549e758..8c9dcfee2 100644 --- a/native/jni/utils/misc.cpp +++ b/native/jni/utils/misc.cpp @@ -268,3 +268,11 @@ int exec_command(int err, int *fd, void (*cb)(void), const char *argv0, ...) { va_end(argv); return pid; } + +char *strdup2(const char *s, size_t *size) { + size_t l = strlen(s) + 1; + char *buf = new char[l]; + memcpy(buf, s, l); + if (size) *size = l; + return buf; +}