diff --git a/native/jni/init/getinfo.cpp b/native/jni/init/getinfo.cpp index 9e6c60fad..90f6ad736 100644 --- a/native/jni/init/getinfo.cpp +++ b/native/jni/init/getinfo.cpp @@ -13,33 +13,48 @@ using namespace std; vector mount_list; -template -static void parse_cmdline(const Func &fn) { - char cmdline[4096]; - int fd = xopen("/proc/cmdline", O_RDONLY | O_CLOEXEC); - cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0'; - close(fd); - - char *tok, *eql, *tmp, *saveptr; - saveptr = cmdline; - while ((tok = strtok_r(nullptr, " \n", &saveptr)) != nullptr) { - eql = strchr(tok, '='); - if (eql) { - *eql = '\0'; - if (eql[1] == '"') { - tmp = strchr(saveptr, '"'); - if (tmp != nullptr) { - *tmp = '\0'; - saveptr[-1] = ' '; - saveptr = tmp + 1; - eql++; - } - } - fn(tok, eql + 1); +static vector> parse_cmdline(const string &cmdline) { + vector> result; + size_t base = 0; + while (true) { + auto found = base; + while (((found = cmdline.find_first_of(" \"", found)) != string::npos) && + (cmdline[found] == '"')) { + if ((found = cmdline.find('"', found + 1)) == string::npos) + break; + found++; + } + string piece; + auto source = cmdline.substr(base, found - base); + remove_copy(source.begin(), source.end(), back_insert_iterator(piece), '"'); + auto equal_sign = piece.find('='); + if (equal_sign == string::npos) { + if (!piece.empty()) + result.emplace_back(std::move(piece), ""); } else { - fn(tok, ""); + result.emplace_back(piece.substr(0, equal_sign), piece.substr(equal_sign + 1)); + } + if (found == string::npos) + break; + base = found + 1; + } + return result; +} + +static vector> parse_bootconfig(const string &bootconfig) { + vector> result; + for (auto &line : split(bootconfig, "\n")) { + line.erase(remove(line.begin(), line.end(), '"'), line.end()); + auto equal_sign = line.find('='); + if (equal_sign == string::npos) { + if (!line.empty()) + result.emplace_back(move(line), ""); + } else { + result.emplace_back(rtrim(line.substr(0, equal_sign)), + ltrim(line.substr(equal_sign + 1))); } } + return result; } #define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8))) @@ -155,12 +170,12 @@ void load_kernel_info(cmdline *cmd) { // Log to kernel setup_klog(); - parse_cmdline([=](string_view key, const char *value) { + for (const auto&[key, value] : parse_cmdline(full_read("/proc/cmdline"))) { if (key == "androidboot.slot_suffix") { - strcpy(cmd->slot, value); + strcpy(cmd->slot, value.data()); } else if (key == "androidboot.slot") { cmd->slot[0] = '_'; - strcpy(cmd->slot + 1, value); + strcpy(cmd->slot + 1, value.data()); } else if (key == "skip_initramfs") { cmd->skip_initramfs = true; } else if (key == "androidboot.force_normal_boot") { @@ -168,15 +183,15 @@ void load_kernel_info(cmdline *cmd) { } else if (key == "rootwait") { cmd->rootwait = true; } else if (key == "androidboot.android_dt_dir") { - strcpy(cmd->dt_dir, value); + strcpy(cmd->dt_dir, value.data()); } else if (key == "androidboot.hardware") { - strcpy(cmd->hardware, value); + strcpy(cmd->hardware, value.data()); } else if (key == "androidboot.hardware.platform") { - strcpy(cmd->hardware_plat, value); + strcpy(cmd->hardware_plat, value.data()); } else if (key == "androidboot.fstab_suffix") { - strcpy(cmd->fstab_suffix, value); + strcpy(cmd->fstab_suffix, value.data()); } - }); + } LOGD("Kernel cmdline info:\n"); LOGD("skip_initramfs=[%d]\n", cmd->skip_initramfs); @@ -188,6 +203,30 @@ void load_kernel_info(cmdline *cmd) { LOGD("hardware=[%s]\n", cmd->hardware); LOGD("hardware.platform=[%s]\n", cmd->hardware_plat); + for (const auto&[key, value] : parse_bootconfig(full_read("/proc/bootconfig"))) { + if (key == "androidboot.slot_suffix") { + strcpy(cmd->slot, value.data()); + } else if (key == "androidboot.force_normal_boot") { + cmd->force_normal_boot = value[0] == '1'; + } else if (key == "androidboot.android_dt_dir") { + strcpy(cmd->dt_dir, value.data()); + } else if (key == "androidboot.hardware") { + strcpy(cmd->hardware, value.data()); + } else if (key == "androidboot.hardware.platform") { + strcpy(cmd->hardware_plat, value.data()); + } else if (key == "androidboot.fstab_suffix") { + strcpy(cmd->fstab_suffix, value.data()); + } + } + + LOGD("Boot config info:\n"); + LOGD("force_normal_boot=[%d]\n", cmd->force_normal_boot); + LOGD("slot=[%s]\n", cmd->slot); + LOGD("dt_dir=[%s]\n", cmd->dt_dir); + LOGD("fstab_suffix=[%s]\n", cmd->fstab_suffix); + LOGD("hardware=[%s]\n", cmd->hardware); + LOGD("hardware.platform=[%s]\n", cmd->hardware_plat); + parse_prop_file("/.backup/.magisk", [=](auto key, auto value) -> bool { if (key == "RECOVERYMODE" && value == "true") { LOGD("Running in recovery mode, waiting for key...\n"); diff --git a/native/jni/init/mount.cpp b/native/jni/init/mount.cpp index d5d235228..8fc15e78d 100644 --- a/native/jni/init/mount.cpp +++ b/native/jni/init/mount.cpp @@ -10,13 +10,6 @@ using namespace std; -static string rtrim(string &&str) { - // Trim space, newline, and null byte from end of string - while (memchr(" \n\r", str[str.length() - 1], 4)) - str.pop_back(); - return std::move(str); -} - struct devinfo { int major; int minor; diff --git a/native/jni/utils/misc.cpp b/native/jni/utils/misc.cpp index 8a04dfcde..68bf99b65 100644 --- a/native/jni/utils/misc.cpp +++ b/native/jni/utils/misc.cpp @@ -188,3 +188,16 @@ string &replace_all(string &str, string_view from, string_view to) { } return str; } + +vector split(const string& s, const string& delimiters) { + vector result; + size_t base = 0; + size_t found; + while (true) { + found = s.find_first_of(delimiters, base); + result.push_back(s.substr(base, found - base)); + if (found == string::npos) break; + base = found + 1; + } + return result; +} diff --git a/native/jni/utils/misc.hpp b/native/jni/utils/misc.hpp index cda1f75f2..23acda4b2 100644 --- a/native/jni/utils/misc.hpp +++ b/native/jni/utils/misc.hpp @@ -92,6 +92,18 @@ static inline bool str_starts(std::string_view s, std::string_view ss) { static inline bool str_ends(std::string_view s, std::string_view ss) { return s.size() >= ss.size() && s.compare(s.size() - ss.size(), std::string::npos, ss) == 0; } +static inline std::string ltrim(std::string &&s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); + return std::move(s); +} +static inline std::string rtrim(std::string &&s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch) && ch != '\0'; + }).base(), s.end()); + return std::move(s); +} int fork_dont_care(); int fork_no_orphan(); @@ -101,6 +113,7 @@ uint32_t binary_gcd(uint32_t u, uint32_t v); int switch_mnt_ns(int pid); int gen_rand_str(char *buf, int len, bool varlen = true); std::string &replace_all(std::string &str, std::string_view from, std::string_view to); +std::vector split(const std::string& s, const std::string& delimiters); struct exec_t { bool err = false;