mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-13 05:37:47 +02:00
Minor optimizations
This commit is contained in:
@ -30,7 +30,7 @@ string node_entry::mirror_dir;
|
|||||||
*************************/
|
*************************/
|
||||||
|
|
||||||
tmpfs_node::tmpfs_node(node_entry *node) : dir_node(node, this) {
|
tmpfs_node::tmpfs_node(node_entry *node) : dir_node(node, this) {
|
||||||
if (!skip_mirror) {
|
if (!skip_mirror()) {
|
||||||
string mirror = mirror_path();
|
string mirror = mirror_path();
|
||||||
if (auto dir = open_dir(mirror.data())) {
|
if (auto dir = open_dir(mirror.data())) {
|
||||||
set_exist(true);
|
set_exist(true);
|
||||||
@ -54,14 +54,11 @@ tmpfs_node::tmpfs_node(node_entry *node) : dir_node(node, this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool dir_node::prepare() {
|
bool dir_node::prepare() {
|
||||||
bool to_tmpfs = skip_mirror;
|
// If direct replace or not exist, mount ourselves as tmpfs
|
||||||
if (!exist()) {
|
bool upgrade_to_tmpfs = skip_mirror() || !exist();
|
||||||
// If not exist, we need to create it by mounting tmpfs
|
|
||||||
to_tmpfs = true;
|
|
||||||
set_exist(true);
|
|
||||||
}
|
|
||||||
for (auto it = children.begin(); it != children.end();) {
|
for (auto it = children.begin(); it != children.end();) {
|
||||||
// We need to upgrade to tmpfs node if any child:
|
// We also need to upgrade to tmpfs node if any child:
|
||||||
// - Target does not exist
|
// - Target does not exist
|
||||||
// - Source or target is a symlink (since we cannot bind mount symlink)
|
// - Source or target is a symlink (since we cannot bind mount symlink)
|
||||||
bool cannot_mnt;
|
bool cannot_mnt;
|
||||||
@ -80,12 +77,12 @@ bool dir_node::prepare() {
|
|||||||
it = children.erase(it);
|
it = children.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Tell parent to upgrade self to tmpfs
|
upgrade_to_tmpfs = true;
|
||||||
to_tmpfs = true;
|
|
||||||
}
|
}
|
||||||
if (auto dn = dyn_cast<dir_node>(it->second)) {
|
if (auto dn = dyn_cast<dir_node>(it->second)) {
|
||||||
if (skip_mirror) {
|
if (skip_mirror()) {
|
||||||
dn->skip_mirror = true;
|
// Propagate skip mirror state to all children
|
||||||
|
dn->set_skip_mirror(true);
|
||||||
}
|
}
|
||||||
if (dn->prepare()) {
|
if (dn->prepare()) {
|
||||||
// Upgrade child to tmpfs
|
// Upgrade child to tmpfs
|
||||||
@ -94,7 +91,7 @@ bool dir_node::prepare() {
|
|||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
return to_tmpfs;
|
return upgrade_to_tmpfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dir_node::collect_module_files(const char *module, int dfd) {
|
void dir_node::collect_module_files(const char *module, int dfd) {
|
||||||
@ -103,20 +100,20 @@ void dir_node::collect_module_files(const char *module, int dfd) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
inter_node *dn;
|
|
||||||
if (entry->d_name == ".replace"sv) {
|
if (entry->d_name == ".replace"sv) {
|
||||||
skip_mirror = true;
|
set_skip_mirror(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry->d_type == DT_DIR) {
|
if (entry->d_type == DT_DIR) {
|
||||||
|
inter_node *node;
|
||||||
if (auto it = children.find(entry->d_name); it == children.end()) {
|
if (auto it = children.find(entry->d_name); it == children.end()) {
|
||||||
dn = emplace<inter_node>(entry->d_name, entry->d_name);
|
node = emplace<inter_node>(entry->d_name, entry->d_name);
|
||||||
} else {
|
} else {
|
||||||
dn = dyn_cast<inter_node>(it->second);
|
node = dyn_cast<inter_node>(it->second);
|
||||||
}
|
}
|
||||||
if (dn) {
|
if (node) {
|
||||||
dn->collect_module_files(module, dirfd(dir.get()));
|
node->collect_module_files(module, dirfd(dir.get()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emplace<module_node>(entry->d_name, module, entry);
|
emplace<module_node>(entry->d_name, module, entry);
|
||||||
@ -169,7 +166,7 @@ void tmpfs_node::mount() {
|
|||||||
if (!isa<tmpfs_node>(parent())) {
|
if (!isa<tmpfs_node>(parent())) {
|
||||||
auto worker_dir = MAGISKTMP + "/" WORKERDIR + dest;
|
auto worker_dir = MAGISKTMP + "/" WORKERDIR + dest;
|
||||||
mkdirs(worker_dir.data(), 0);
|
mkdirs(worker_dir.data(), 0);
|
||||||
create_and_mount(skip_mirror ? "replace" : "tmpfs", worker_dir);
|
create_and_mount(skip_mirror() ? "replace" : "tmpfs", worker_dir);
|
||||||
} else {
|
} else {
|
||||||
// We don't need another layer of tmpfs if parent is tmpfs
|
// We don't need another layer of tmpfs if parent is tmpfs
|
||||||
mkdir(dest.data(), 0);
|
mkdir(dest.data(), 0);
|
||||||
|
@ -55,18 +55,23 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
template<class T>
|
template<class T>
|
||||||
node_entry(const char *name, uint8_t file_type, T*)
|
node_entry(const char *name, uint8_t file_type, T*)
|
||||||
: _name(name), _file_type(file_type), _node_type(type_id<T>()) {}
|
: _name(name), _file_type(file_type & 15), _node_type(type_id<T>()) {}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
explicit node_entry(T*) : _file_type(0), _node_type(type_id<T>()) {}
|
explicit node_entry(T*) : _file_type(0), _node_type(type_id<T>()) {}
|
||||||
|
|
||||||
void consume(node_entry *other);
|
virtual void consume(node_entry *other) {
|
||||||
|
_name.swap(other->_name);
|
||||||
|
_file_type = other->_file_type;
|
||||||
|
_parent = other->_parent;
|
||||||
|
delete other;
|
||||||
|
}
|
||||||
|
|
||||||
void create_and_mount(const char *reason, const string &src);
|
void create_and_mount(const char *reason, const string &src);
|
||||||
|
|
||||||
// Use top bit of _file_type for node exist status
|
// Use bit 7 of _file_type for exist status
|
||||||
bool exist() const { return static_cast<bool>(_file_type & (1 << 7)); }
|
bool exist() const { return static_cast<bool>(_file_type & (1 << 7)); }
|
||||||
void set_exist(bool b) { if (b) _file_type |= (1 << 7); else _file_type &= ~(1 << 7); }
|
void set_exist(bool b) { if (b) _file_type |= (1 << 7); else _file_type &= ~(1 << 7); }
|
||||||
uint8_t file_type() const { return static_cast<uint8_t>(_file_type & ~(1 << 7)); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class dir_node;
|
friend class dir_node;
|
||||||
@ -74,21 +79,21 @@ private:
|
|||||||
template<class T>
|
template<class T>
|
||||||
friend bool isa(node_entry *node);
|
friend bool isa(node_entry *node);
|
||||||
|
|
||||||
|
uint8_t file_type() const { return static_cast<uint8_t>(_file_type & 15); }
|
||||||
|
|
||||||
// Node properties
|
// Node properties
|
||||||
string _name;
|
string _name;
|
||||||
uint8_t _file_type;
|
|
||||||
const uint8_t _node_type;
|
|
||||||
|
|
||||||
dir_node *_parent = nullptr;
|
dir_node *_parent = nullptr;
|
||||||
|
|
||||||
// Cache, it should only be used within prepare
|
// Cache, it should only be used within prepare
|
||||||
string _node_path;
|
string _node_path;
|
||||||
|
|
||||||
|
uint8_t _file_type;
|
||||||
|
const uint8_t _node_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
class dir_node : public node_entry {
|
class dir_node : public node_entry {
|
||||||
public:
|
public:
|
||||||
friend void node_entry::consume(node_entry *other);
|
|
||||||
|
|
||||||
using map_type = map<string_view, node_entry *>;
|
using map_type = map<string_view, node_entry *>;
|
||||||
using iterator = map_type::iterator;
|
using iterator = map_type::iterator;
|
||||||
|
|
||||||
@ -98,6 +103,10 @@ public:
|
|||||||
children.clear();
|
children.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************
|
||||||
|
* Entrypoints
|
||||||
|
**************/
|
||||||
|
|
||||||
// Traverse through module directories to generate a tree of module files
|
// Traverse through module directories to generate a tree of module files
|
||||||
void collect_module_files(const char *module, int dfd);
|
void collect_module_files(const char *module, int dfd);
|
||||||
|
|
||||||
@ -160,16 +169,30 @@ protected:
|
|||||||
template<class T>
|
template<class T>
|
||||||
dir_node(const char *name, T *self) : node_entry(name, DT_DIR, self) {
|
dir_node(const char *name, T *self) : node_entry(name, DT_DIR, self) {
|
||||||
if constexpr (std::is_same_v<T, root_node>)
|
if constexpr (std::is_same_v<T, root_node>)
|
||||||
_root = self;
|
_root = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
dir_node(node_entry *node, T *self) : node_entry(self) {
|
dir_node(node_entry *node, T *self) : node_entry(self) {
|
||||||
consume(node);
|
|
||||||
if constexpr (std::is_same_v<T, root_node>)
|
if constexpr (std::is_same_v<T, root_node>)
|
||||||
_root = self;
|
_root = self;
|
||||||
|
dir_node::consume(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void consume(node_entry *other) override {
|
||||||
|
if (auto o = dyn_cast<dir_node>(other)) {
|
||||||
|
children.merge(o->children);
|
||||||
|
for (auto &pair : children)
|
||||||
|
pair.second->_parent = this;
|
||||||
|
}
|
||||||
|
node_entry::consume(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use bit 6 of _file_type
|
||||||
|
// Skip binding mirror for this directory
|
||||||
|
bool skip_mirror() const { return static_cast<bool>(_file_type & (1 << 6)); }
|
||||||
|
void set_skip_mirror(bool b) { if (b) _file_type |= (1 << 6); else _file_type &= ~(1 << 6); }
|
||||||
|
|
||||||
template<class T = node_entry>
|
template<class T = node_entry>
|
||||||
T *iterator_to_node(iterator it) {
|
T *iterator_to_node(iterator it) {
|
||||||
return static_cast<T*>(it == children.end() ? nullptr : it->second);
|
return static_cast<T*>(it == children.end() ? nullptr : it->second);
|
||||||
@ -229,9 +252,6 @@ protected:
|
|||||||
// dir nodes host children
|
// dir nodes host children
|
||||||
map_type children;
|
map_type children;
|
||||||
|
|
||||||
// Skip binding mirror for this directory
|
|
||||||
bool skip_mirror = false;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Root node lookup cache
|
// Root node lookup cache
|
||||||
root_node *_root = nullptr;
|
root_node *_root = nullptr;
|
||||||
@ -259,7 +279,7 @@ public:
|
|||||||
: node_entry(entry->d_name, entry->d_type, this), module(module) {}
|
: node_entry(entry->d_name, entry->d_type, this), module(module) {}
|
||||||
|
|
||||||
module_node(node_entry *node, const char *module) : node_entry(this), module(module) {
|
module_node(node_entry *node, const char *module) : node_entry(this), module(module) {
|
||||||
consume(node);
|
node_entry::consume(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mount() override;
|
void mount() override;
|
||||||
@ -294,20 +314,3 @@ const string &node_entry::node_path() {
|
|||||||
_node_path = _parent->node_path() + '/' + _name;
|
_node_path = _parent->node_path() + '/' + _name;
|
||||||
return _node_path;
|
return _node_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_entry::consume(node_entry *other) {
|
|
||||||
_name.swap(other->_name);
|
|
||||||
_file_type = other->_file_type;
|
|
||||||
_parent = other->_parent;
|
|
||||||
|
|
||||||
// Merge children if both is dir
|
|
||||||
if (auto a = dyn_cast<dir_node>(this)) {
|
|
||||||
if (auto b = dyn_cast<dir_node>(other)) {
|
|
||||||
a->skip_mirror = b->skip_mirror;
|
|
||||||
a->children.merge(b->children);
|
|
||||||
for (auto &pair : a->children)
|
|
||||||
pair.second->_parent = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete other;
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user