From a7c156a9e3ed96678ac256e9ac0bda0df2f78c9e Mon Sep 17 00:00:00 2001 From: LoveSy Date: Tue, 14 Dec 2021 19:40:23 +0800 Subject: [PATCH] Further fix `oplus.fstab` support * Further fix `oplus.fstab` support In some oneplus devices, `oplus.fstab` does exists but `init` never loaded it and those entries in `oplus.fstab` are written directly to `fstab.qcom`. Previous implementation will introduce duplicate entries to `fstab.qcom` and brick the device. This commit filters those entries from `oplus.fstab` that are already in `fstab.qcom` and further filters duplicated entries in `oplus.fstab` (keep only the last entry). Fix #5016 * Fix UB Since we moved entry, we need to explicitly copy its member. For c++23 we can use `auto{}`. --- native/jni/init/init.hpp | 2 ++ native/jni/init/twostage.cpp | 44 ++++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/native/jni/init/init.hpp b/native/jni/init/init.hpp index 409ed1d9f..75bc4b474 100644 --- a/native/jni/init/init.hpp +++ b/native/jni/init/init.hpp @@ -26,6 +26,8 @@ struct fstab_entry { fstab_entry() = default; fstab_entry(const fstab_entry &) = delete; fstab_entry(fstab_entry &&) = default; + fstab_entry &operator=(const fstab_entry&) = delete; + fstab_entry &operator=(fstab_entry&&) = default; void to_file(FILE *fp); }; diff --git a/native/jni/init/twostage.cpp b/native/jni/init/twostage.cpp index b929435a1..92b8c4719 100644 --- a/native/jni/init/twostage.cpp +++ b/native/jni/init/twostage.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -132,30 +133,43 @@ exit_loop: // Append oppo's custom fstab if (access("oplus.fstab", F_OK) == 0) { LOGD("Found fstab file: %s\n", "oplus.fstab"); - vector oplus_fstab; + set main_mount_point; map bind_map; + map entry_map; - read_fstab_file("oplus.fstab", oplus_fstab); + // used to avoid duplication + for (auto &entry: fstab) { + main_mount_point.emplace(entry.mnt_point); + } - for (auto &entry : oplus_fstab) { - if (entry.mnt_flags.find("bind") != string::npos) { - bind_map.emplace(entry.dev, entry.mnt_point); - entry.dev = ""; + { + vector oplus_fstab; + read_fstab_file("oplus.fstab", oplus_fstab); + + for (auto &entry : oplus_fstab) { + // skip duplicated entry between the main file and the oplus one + if (main_mount_point.count(entry.mnt_point)) continue; + if (entry.mnt_flags.find("bind") != string::npos) { + bind_map.emplace(std::move(entry.dev), std::move(entry.mnt_point)); + } else { + // skip duplicated entry in the same file + entry_map.insert_or_assign(decltype(entry.mnt_point){entry.mnt_point}, std::move(entry)); + } } } - for (auto &entry : oplus_fstab) { - // Merge bind entries - if (entry.dev.empty()) - continue; - auto got = bind_map.find(entry.mnt_point); - if (got != bind_map.end()) - entry.mnt_point = got->second; - - // Mount befor switch root, fix img path + for (auto &[_, entry] : entry_map) { + // Mount before switch root, fix img path if (str_starts(entry.dev, "loop@/system/")) entry.dev.insert(5, "/system_root"); + // change bind mount entries to dev mount since some users reported bind is not working + // in this case, we drop the original mount point and leave only the one from bind entry + // because some users reported keeping the original mount point causes bootloop + if (auto got = bind_map.find(entry.mnt_point); got != bind_map.end()) { + entry.mnt_point = got->second; + } + fstab.push_back(move(entry)); }