Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
6fe9b69a
Commit
6fe9b69a
authored
Aug 28, 2021
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleanup module.cpp
parent
5d162f81
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
99 additions
and
94 deletions
+99
-94
module.cpp
native/jni/core/module.cpp
+99
-94
No files found.
native/jni/core/module.cpp
View file @
6fe9b69a
...
...
@@ -15,11 +15,11 @@ using namespace std;
#define TYPE_MIRROR (1 << 0)
/* mount from mirror */
#define TYPE_INTER (1 << 1)
/* intermediate node */
#define TYPE_
SKEL
(1 << 2)
/* replace with tmpfs */
#define TYPE_
TMPFS
(1 << 2)
/* replace with tmpfs */
#define TYPE_MODULE (1 << 3)
/* mount from module */
#define TYPE_ROOT (1 << 4)
/* partition root */
#define TYPE_CUSTOM (1 << 5)
/* custom node type overrides all */
#define TYPE_DIR (TYPE_INTER|TYPE_
SKEL
|TYPE_ROOT)
#define TYPE_DIR (TYPE_INTER|TYPE_
TMPFS
|TYPE_ROOT)
static
vector
<
string
>
module_list
;
...
...
@@ -27,11 +27,10 @@ class node_entry;
class
dir_node
;
class
inter_node
;
class
mirror_node
;
class
skel
_node
;
class
tmpfs
_node
;
class
module_node
;
class
root_node
;
static
void
merge_node
(
node_entry
*
a
,
node_entry
*
b
);
template
<
class
T
>
static
bool
isa
(
node_entry
*
node
);
static
int
bind_mount
(
const
char
*
from
,
const
char
*
to
)
{
int
ret
=
xmount
(
from
,
to
,
nullptr
,
MS_BIND
,
nullptr
);
...
...
@@ -44,7 +43,7 @@ template<class T> uint8_t type_id() { return TYPE_CUSTOM; }
template
<>
uint8_t
type_id
<
dir_node
>
()
{
return
TYPE_DIR
;
}
template
<>
uint8_t
type_id
<
inter_node
>
()
{
return
TYPE_INTER
;
}
template
<>
uint8_t
type_id
<
mirror_node
>
()
{
return
TYPE_MIRROR
;
}
template
<>
uint8_t
type_id
<
skel_node
>
()
{
return
TYPE_SKEL
;
}
template
<>
uint8_t
type_id
<
tmpfs_node
>
()
{
return
TYPE_TMPFS
;
}
template
<>
uint8_t
type_id
<
module_node
>
()
{
return
TYPE_MODULE
;
}
template
<>
uint8_t
type_id
<
root_node
>
()
{
return
TYPE_ROOT
;
}
...
...
@@ -52,18 +51,18 @@ class node_entry {
public
:
virtual
~
node_entry
()
=
default
;
// Node info
bool
is_dir
()
{
return
file_type
()
==
DT_DIR
;
}
bool
is_lnk
()
{
return
file_type
()
==
DT_LNK
;
}
bool
is_reg
()
{
return
file_type
()
==
DT_REG
;
}
uint8_t
type
()
{
return
node_type
;
}
const
string
&
name
()
{
return
_name
;
}
// Paths
const
string
&
node_path
();
string
mirror_path
()
{
return
mirror_dir
+
node_path
();
}
// Tree methods
dir_node
*
parent
()
{
return
_parent
;
}
void
merge
(
node_entry
*
other
);
virtual
void
mount
()
=
0
;
...
...
@@ -76,20 +75,19 @@ protected:
:
_name
(
name
),
_file_type
(
file_type
),
node_type
(
type_id
<
T
>
())
{}
template
<
class
T
>
explicit
node_entry
(
T
*
)
:
node_type
(
type_id
<
T
>
())
{}
explicit
node_entry
(
T
*
)
:
_file_type
(
0
),
node_type
(
type_id
<
T
>
())
{}
void
create_and_mount
(
const
string
&
src
);
/
* Use top bit of _file_type for node exist status */
/
/ Use top bit of _file_type for node exist status
bool
exist
()
{
return
static_cast
<
bool
>
(
_file_type
&
(
1
<<
7
));
}
void
set_exist
(
bool
b
)
{
if
(
b
)
_file_type
|=
(
1
<<
7
);
else
_file_type
&=
~
(
1
<<
7
);
}
uint8_t
file_type
()
{
return
static_cast
<
uint8_t
>
(
_file_type
&
~
(
1
<<
7
));
}
private
:
friend
void
merge_node
(
node_entry
*
a
,
node_entry
*
b
);
friend
class
dir_node
;
bool
need_skel_upgrade
(
node_entry
*
child
);
static
bool
should_be_tmpfs
(
node_entry
*
child
);
// Node properties
string
_name
;
...
...
@@ -104,10 +102,10 @@ private:
class
dir_node
:
public
node_entry
{
public
:
friend
void
merge_node
(
node_entry
*
a
,
node_entry
*
b
);
friend
void
node_entry
::
merge
(
node_entry
*
other
);
typedef
map
<
string_view
,
node_entry
*>
map_type
;
typedef
map_type
::
iterator
map_ite
r
;
using
map_type
=
map
<
string_view
,
node_entry
*>
;
using
iterator
=
map_type
::
iterato
r
;
~
dir_node
()
override
{
for
(
auto
&
it
:
children
)
...
...
@@ -134,7 +132,7 @@ public:
bool
is_empty
()
{
return
children
.
empty
();
}
template
<
class
T
>
T
*
child
(
string_view
name
)
{
return
iter_to_node
<
T
>
(
children
.
find
(
name
));
}
T
*
child
(
string_view
name
)
{
return
iter
ator
_to_node
<
T
>
(
children
.
find
(
name
));
}
// Lazy val
root_node
*
root
()
{
...
...
@@ -148,30 +146,28 @@ public:
// Return false if rejected
bool
insert
(
node_entry
*
node
)
{
return
node
?
iter_to_node
(
insert
(
children
.
find
(
node
->
_name
),
node
->
node_type
,
[
=
](
auto
_
)
{
return
node
;
}))
!=
nullptr
:
false
;
auto
fn
=
[
=
](
auto
)
{
return
node
;
};
return
node
&&
iterator_to_node
(
insert
(
node
->
_name
,
node
->
node_type
,
fn
));
}
// Return inserted node or null if rejected
template
<
class
T
,
class
...
Args
>
T
*
emplace
(
string_view
name
,
Args
&&
...
args
)
{
return
iter_to_node
<
T
>
(
insert
(
children
.
find
(
name
),
type_id
<
T
>
(),
[
&
](
auto
_
)
{
return
new
T
(
std
::
forward
<
Args
>
(
args
)...);
}
));
auto
fn
=
[
&
](
auto
)
{
return
new
T
(
std
::
forward
<
Args
>
(
args
)...);
};
return
iterator_to_node
<
T
>
(
insert
(
name
,
type_id
<
T
>
(),
fn
));
}
// Return inserted node, existing node with same rank, or null
// Return inserted node, existing node with same rank, or null
if rejected
template
<
class
T
,
class
...
Args
>
T
*
emplace_or_get
(
string_view
name
,
Args
&&
...
args
)
{
return
iter_to_node
<
T
>
(
insert
(
children
.
find
(
name
),
type_id
<
T
>
(),
[
&
](
auto
_
)
{
return
new
T
(
std
::
forward
<
Args
>
(
args
)...);
}
,
true
));
auto
fn
=
[
&
](
auto
)
{
return
new
T
(
std
::
forward
<
Args
>
(
args
)...);
};
return
iterator_to_node
<
T
>
(
insert
(
name
,
type_id
<
T
>
(),
fn
,
true
));
}
// Return upgraded node or null if rejected
template
<
class
T
,
class
...
Args
>
T
*
upgrade
(
string_view
name
,
Args
&
...
args
)
{
return
iter_to_node
<
T
>
(
upgrade
<
T
>
(
children
.
find
(
name
),
args
...));
return
iter
ator
_to_node
<
T
>
(
upgrade
<
T
>
(
children
.
find
(
name
),
args
...));
}
protected
:
...
...
@@ -183,7 +179,7 @@ protected:
template
<
class
T
>
dir_node
(
node_entry
*
node
,
T
*
self
)
:
node_entry
(
self
)
{
merge
_node
(
this
,
node
);
merge
(
node
);
if
constexpr
(
std
::
is_same_v
<
T
,
root_node
>
)
_root
=
self
;
}
...
...
@@ -192,33 +188,27 @@ protected:
dir_node
(
const
char
*
name
,
T
*
self
)
:
dir_node
(
name
,
DT_DIR
,
self
)
{}
template
<
class
T
=
node_entry
>
T
*
iter
_to_node
(
const
map_iter
&
it
)
{
return
reinterpret
_cast
<
T
*>
(
it
==
children
.
end
()
?
nullptr
:
it
->
second
);
T
*
iter
ator_to_node
(
iterator
it
)
{
return
static
_cast
<
T
*>
(
it
==
children
.
end
()
?
nullptr
:
it
->
second
);
}
/* fn signature: (node_ent *&) -> node_ent *
* fn gets reference to the existing node, may be null.
* If fn consumes input, need to set reference to null.
* Returns new node or null to reject the insertion. */
// Emplace insert a new node, or upgrade if the requested type has a higher rank.
// Return iterator to new node or end() if insertion is rejected.
// If get_same is true and a node with the same rank exists, it will return that node instead.
// fn is the node construction callback. Signature: (node_ent *&) -> node_ent *
// fn gets a reference to the existing node pointer and returns a new node object.
// Input is null when there is no existing node. If returns null, the insertion is rejected.
// If fn consumes the input, it should set the reference to null.
template
<
typename
Func
>
iterator
insert
(
iterator
it
,
uint8_t
type
,
const
Func
&
fn
,
bool
get_same
);
template
<
typename
Func
>
map_iter
insert
(
map_iter
it
,
uint8_t
type
,
Func
fn
,
bool
allow_same
=
false
);
iterator
insert
(
string_view
name
,
uint8_t
type
,
const
Func
&
fn
,
bool
get_same
=
false
)
{
return
insert
(
children
.
find
(
name
),
type
,
fn
,
get_same
);
}
template
<
class
To
,
class
From
=
node_entry
,
class
...
Args
>
map_iter
upgrade
(
map_iter
it
,
Args
&&
...
args
)
{
return
insert
(
it
,
type_id
<
To
>
(),
[
&
](
node_entry
*&
ex
)
->
node_entry
*
{
if
(
!
ex
)
return
nullptr
;
if
constexpr
(
!
std
::
is_same_v
<
From
,
node_entry
>
)
{
// Type check if specific type is selected
if
(
!
isa
<
From
>
(
ex
))
return
nullptr
;
}
auto
node
=
new
To
(
reinterpret_cast
<
From
*>
(
ex
),
std
::
forward
<
Args
>
(
args
)...);
ex
=
nullptr
;
return
node
;
});
}
iterator
upgrade
(
iterator
it
,
Args
&&
...
args
);
// dir nodes host children
map_type
children
;
...
...
@@ -248,7 +238,7 @@ public:
:
node_entry
(
entry
->
d_name
,
entry
->
d_type
,
this
),
module
(
module
)
{}
module_node
(
node_entry
*
node
,
const
char
*
module
)
:
node_entry
(
this
),
module
(
module
)
{
merge
_node
(
this
,
node
);
merge
(
node
);
}
explicit
module_node
(
inter_node
*
node
)
:
module_node
(
node
,
node
->
module
)
{}
...
...
@@ -266,9 +256,9 @@ public:
}
};
class
skel
_node
:
public
dir_node
{
class
tmpfs
_node
:
public
dir_node
{
public
:
explicit
skel
_node
(
node_entry
*
node
);
explicit
tmpfs
_node
(
node_entry
*
node
);
void
mount
()
override
;
};
...
...
@@ -279,29 +269,29 @@ static bool isa(node_entry *node) {
}
template
<
class
T
>
static
T
*
dyn_cast
(
node_entry
*
node
)
{
return
isa
<
T
>
(
node
)
?
reinterpret
_cast
<
T
*>
(
node
)
:
nullptr
;
return
isa
<
T
>
(
node
)
?
static
_cast
<
T
*>
(
node
)
:
nullptr
;
}
// Merge b -> a, b will be deleted
static
void
merge_node
(
node_entry
*
a
,
node_entry
*
b
)
{
a
->
_name
.
swap
(
b
->
_name
);
a
->
_file_type
=
b
->
_file_type
;
a
->
_parent
=
b
->
_parent
;
string
node_entry
::
module_mnt
;
string
node_entry
::
mirror_dir
;
// other will be deleted
void
node_entry
::
merge
(
node_entry
*
other
)
{
_name
.
swap
(
other
->
_name
);
_file_type
=
other
->
_file_type
;
_parent
=
other
->
_parent
;
// Merge children if both is dir
if
(
auto
a
a
=
dyn_cast
<
dir_node
>
(
a
);
aa
)
{
if
(
auto
b
b
=
dyn_cast
<
dir_node
>
(
b
);
bb
)
{
a
a
->
children
.
merge
(
b
b
->
children
);
for
(
auto
&
pair
:
a
a
->
children
)
pair
.
second
->
_parent
=
a
a
;
if
(
auto
a
=
dyn_cast
<
dir_node
>
(
this
)
)
{
if
(
auto
b
=
dyn_cast
<
dir_node
>
(
other
)
)
{
a
->
children
.
merge
(
b
->
children
);
for
(
auto
&
pair
:
a
->
children
)
pair
.
second
->
_parent
=
a
;
}
}
delete
b
;
delete
other
;
}
string
node_entry
::
module_mnt
;
string
node_entry
::
mirror_dir
;
const
string
&
node_entry
::
node_path
()
{
if
(
_parent
&&
_node_path
.
empty
())
_node_path
=
_parent
->
node_path
()
+
'/'
+
_name
;
...
...
@@ -313,16 +303,16 @@ const string &node_entry::node_path() {
*************************/
template
<
typename
Func
>
dir_node
::
map_iter
dir_node
::
insert
(
dir_node
::
map_iter
it
,
uint8_t
type
,
Func
fn
,
bool
allow
_same
)
{
dir_node
::
iterator
dir_node
::
insert
(
iterator
it
,
uint8_t
type
,
const
Func
&
fn
,
bool
get
_same
)
{
node_entry
*
node
=
nullptr
;
if
(
it
!=
children
.
end
())
{
// Upgrade existing node only if higher rank
if
(
it
->
second
->
node_type
<
type
)
{
// Upgrade existing node only if higher precedence
node
=
fn
(
it
->
second
);
if
(
!
node
)
return
children
.
end
();
if
(
it
->
second
)
merge_node
(
node
,
it
->
second
);
node
->
merge
(
it
->
second
);
it
=
children
.
erase
(
it
);
// Minor optimization to make insert O(1) by using hint
if
(
it
==
children
.
begin
())
...
...
@@ -330,20 +320,36 @@ dir_node::map_iter dir_node::insert(dir_node::map_iter it, uint8_t type, Func fn
else
it
=
children
.
emplace_hint
(
--
it
,
node
->
_name
,
node
);
}
else
{
if
(
allow
_same
&&
it
->
second
->
node_type
==
type
)
if
(
get
_same
&&
it
->
second
->
node_type
==
type
)
return
it
;
return
children
.
end
();
}
}
else
{
node
=
fn
(
node
);
if
(
!
node
)
return
it
;
return
children
.
end
()
;
node
->
_parent
=
this
;
it
=
children
.
emplace
(
node
->
_name
,
node
).
first
;
}
return
it
;
}
template
<
class
To
,
class
From
,
class
...
Args
>
dir_node
::
iterator
dir_node
::
upgrade
(
iterator
it
,
Args
&&
...
args
)
{
return
insert
(
it
,
type_id
<
To
>
(),
[
&
](
node_entry
*&
ex
)
->
node_entry
*
{
if
(
!
ex
)
return
nullptr
;
if
constexpr
(
!
std
::
is_same_v
<
From
,
node_entry
>
)
{
// Type check if type is specified
if
(
!
isa
<
From
>
(
ex
))
return
nullptr
;
}
auto
node
=
new
To
(
static_cast
<
From
*>
(
ex
),
std
::
forward
<
Args
>
(
args
)...);
ex
=
nullptr
;
return
node
;
},
false
);
}
node_entry
*
dir_node
::
extract
(
string_view
name
)
{
auto
it
=
children
.
find
(
name
);
if
(
it
!=
children
.
end
())
{
...
...
@@ -354,9 +360,9 @@ node_entry* dir_node::extract(string_view name) {
return
nullptr
;
}
skel_node
::
skel
_node
(
node_entry
*
node
)
:
dir_node
(
node
,
this
)
{
tmpfs_node
::
tmpfs
_node
(
node_entry
*
node
)
:
dir_node
(
node
,
this
)
{
string
mirror
=
mirror_path
();
if
(
auto
dir
=
open_dir
(
mirror
.
data
())
;
dir
)
{
if
(
auto
dir
=
open_dir
(
mirror
.
data
()))
{
set_exist
(
true
);
for
(
dirent
*
entry
;
(
entry
=
xreaddir
(
dir
.
get
()));)
{
// Insert mirror nodes
...
...
@@ -370,40 +376,39 @@ skel_node::skel_node(node_entry *node) : dir_node(node, this) {
}
for
(
auto
it
=
children
.
begin
();
it
!=
children
.
end
();
++
it
)
{
// Need to upgrade all inter_node children to
skel
_node
// Need to upgrade all inter_node children to
tmpfs
_node
if
(
isa
<
inter_node
>
(
it
->
second
))
it
=
upgrade
<
skel
_node
>
(
it
);
it
=
upgrade
<
tmpfs
_node
>
(
it
);
}
}
bool
node_entry
::
need_skel_upgrade
(
node_entry
*
child
)
{
/* We need to upgrade to skeleton if:
* - Target does not exist
* - Source or target is a symlink */
bool
upgrade
=
false
;
// We need to upgrade to tmpfs node if any child:
// - Target does not exist
// - Source or target is a symlink
bool
node_entry
::
should_be_tmpfs
(
node_entry
*
child
)
{
struct
stat
st
;
if
(
lstat
(
child
->
node_path
().
data
(),
&
st
)
!=
0
)
{
upgrade
=
true
;
return
true
;
}
else
{
child
->
set_exist
(
true
);
if
(
child
->
is_lnk
()
||
S_ISLNK
(
st
.
st_mode
))
upgrade
=
true
;
return
true
;
}
return
upgrad
e
;
return
fals
e
;
}
bool
dir_node
::
prepare
()
{
bool
to_
skel
=
false
;
bool
to_
tmpfs
=
false
;
for
(
auto
it
=
children
.
begin
();
it
!=
children
.
end
();)
{
if
(
need_skel_upgrade
(
it
->
second
))
{
if
(
node_type
>
type_id
<
skel
_node
>
())
{
if
(
should_be_tmpfs
(
it
->
second
))
{
if
(
node_type
>
type_id
<
tmpfs
_node
>
())
{
// Upgrade will fail, remove the unsupported child node
delete
it
->
second
;
it
=
children
.
erase
(
it
);
continue
;
}
// Tell parent to upgrade self to
skel
to_
skel
=
true
;
// Tell parent to upgrade self to
tmpfs
to_
tmpfs
=
true
;
// If child is inter_node, upgrade to module
if
(
auto
nit
=
upgrade
<
module_node
,
inter_node
>
(
it
);
nit
!=
children
.
end
())
{
it
=
nit
;
...
...
@@ -411,13 +416,13 @@ bool dir_node::prepare() {
}
}
if
(
auto
dn
=
dyn_cast
<
dir_node
>
(
it
->
second
);
dn
&&
dn
->
is_dir
()
&&
!
dn
->
prepare
())
{
// Upgrade child to
skeleton
it
=
upgrade
<
skel
_node
>
(
it
);
// Upgrade child to
tmpfs
it
=
upgrade
<
tmpfs
_node
>
(
it
);
}
next_node
:
++
it
;
}
return
!
to_
skel
;
return
!
to_
tmpfs
;
}
bool
dir_node
::
collect_files
(
const
char
*
module
,
int
dfd
)
{
...
...
@@ -469,13 +474,13 @@ void module_node::mount() {
string
src
=
module_mnt
+
module
+
parent
()
->
root
()
->
prefix
+
node_path
();
if
(
exist
())
clone_attr
(
mirror_path
().
data
(),
src
.
data
());
if
(
isa
<
skel
_node
>
(
parent
()))
if
(
isa
<
tmpfs
_node
>
(
parent
()))
create_and_mount
(
src
);
else
if
(
is_dir
()
||
is_reg
())
bind_mount
(
src
.
data
(),
node_path
().
data
());
}
void
skel
_node
::
mount
()
{
void
tmpfs
_node
::
mount
()
{
if
(
!
exist
())
return
;
string
src
=
mirror_path
();
...
...
@@ -483,7 +488,7 @@ void skel_node::mount() {
file_attr
a
;
getattr
(
src
.
data
(),
&
a
);
mkdir
(
dest
.
data
(),
0
);
if
(
!
isa
<
skel
_node
>
(
parent
()))
{
if
(
!
isa
<
tmpfs
_node
>
(
parent
()))
{
// We don't need another layer of tmpfs if parent is skel
xmount
(
"tmpfs"
,
dest
.
data
(),
"tmpfs"
,
0
,
nullptr
);
VLOGD
(
"mnt_tmp"
,
"tmpfs"
,
dest
.
data
());
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment