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{}`.
This commit is contained in:
LoveSy 2021-12-14 19:40:23 +08:00 committed by GitHub
parent d81ca77231
commit a7c156a9e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 15 deletions

View File

@ -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);
};

View File

@ -8,6 +8,7 @@
#include <sys/mount.h>
#include <map>
#include <set>
#include <magisk.hpp>
#include <utils.hpp>
@ -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<fstab_entry> oplus_fstab;
set<string> main_mount_point;
map<string, string> bind_map;
map<string, fstab_entry> 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<fstab_entry> 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));
}