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
1777d9f7
Commit
1777d9f7
authored
Jun 11, 2017
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Magic Mount algorithm massive bug fix
parent
309b99ea
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
86 additions
and
54 deletions
+86
-54
bootstages.c
jni/daemon/bootstages.c
+85
-54
misc.c
jni/utils/misc.c
+1
-0
No files found.
jni/daemon/bootstages.c
View file @
1777d9f7
...
@@ -29,11 +29,13 @@ static int debug_log_pid, debug_log_fd;
...
@@ -29,11 +29,13 @@ static int debug_log_pid, debug_log_fd;
* Node structure *
* Node structure *
******************/
******************/
// Precedence: MODULE > SKEL > DUMMY
// Precedence: MODULE > SKEL > INTER > DUMMY
#define DO_NOTHING 0x0
/* intermediate node */
#define IS_DUMMY 0x01
/* mount from mirror */
#define IS_DUMMY 0x1
/* mount from mirror */
#define IS_INTER 0x02
/* intermediate node */
#define IS_SKEL 0x2
/* mount from skeleton */
#define IS_SKEL 0x04
/* mount from skeleton */
#define IS_MODULE 0x4
/* mount from module */
#define IS_MODULE 0x08
/* mount from module */
#define IS_VENDOR 0x10
/* special vendor placeholder */
struct
node_entry
{
struct
node_entry
{
const
char
*
module
;
/* Only used when status & IS_MODULE */
const
char
*
module
;
/* Only used when status & IS_MODULE */
...
@@ -252,9 +254,7 @@ static struct node_entry *insert_child(struct node_entry *p, struct node_entry *
...
@@ -252,9 +254,7 @@ static struct node_entry *insert_child(struct node_entry *p, struct node_entry *
// Exist duplicate
// Exist duplicate
if
(
c
->
status
>
e
->
status
)
{
if
(
c
->
status
>
e
->
status
)
{
// Precedence is higher, replace with new node
// Precedence is higher, replace with new node
c
->
children
=
e
->
children
;
// Preserve all children
destroy_subtree
(
e
);
free
(
e
->
name
);
free
(
e
);
vec_entry
(
p
->
children
)[
_
]
=
c
;
vec_entry
(
p
->
children
)[
_
]
=
c
;
return
c
;
return
c
;
}
else
{
}
else
{
...
@@ -289,24 +289,43 @@ static void construct_tree(const char *module, struct node_entry *parent) {
...
@@ -289,24 +289,43 @@ static void construct_tree(const char *module, struct node_entry *parent) {
node
->
name
=
strdup
(
entry
->
d_name
);
node
->
name
=
strdup
(
entry
->
d_name
);
node
->
type
=
entry
->
d_type
;
node
->
type
=
entry
->
d_type
;
snprintf
(
buf
,
PATH_MAX
,
"%s/%s"
,
parent_path
,
node
->
name
);
snprintf
(
buf
,
PATH_MAX
,
"%s/%s"
,
parent_path
,
node
->
name
);
// Check if the entry has a correspond target
/*
* Clone the parent in the following condition:
* 1. File in module is a symlink
* 2. Target file do not exist
* 3. Target file is a symlink, but not /system/vendor
*/
int
clone
=
0
;
if
(
IS_LNK
(
node
)
||
access
(
buf
,
F_OK
)
==
-
1
)
{
if
(
IS_LNK
(
node
)
||
access
(
buf
,
F_OK
)
==
-
1
)
{
clone
=
1
;
}
else
if
(
strcmp
(
parent
->
name
,
"/system"
)
!=
0
||
strcmp
(
node
->
name
,
"vendor"
)
!=
0
)
{
struct
stat
s
;
xstat
(
buf
,
&
s
);
if
(
S_ISLNK
(
s
.
st_mode
))
clone
=
1
;
}
if
(
clone
)
{
// Mark the parent folder as a skeleton
// Mark the parent folder as a skeleton
parent
->
status
|=
IS_SKEL
;
parent
->
status
|=
IS_SKEL
;
/* This will not overwrite if parent is module */
node
->
status
|
=
IS_MODULE
;
node
->
status
=
IS_MODULE
;
}
else
if
(
IS_DIR
(
node
))
{
}
else
if
(
IS_DIR
(
node
))
{
// Check if marked as replace
// Check if marked as replace
snprintf
(
buf2
,
PATH_MAX
,
"%s/%s%s/.replace"
,
MOUNTPOINT
,
module
,
buf
);
snprintf
(
buf2
,
PATH_MAX
,
"%s/%s%s/.replace"
,
MOUNTPOINT
,
module
,
buf
);
if
(
access
(
buf2
,
F_OK
)
==
0
)
{
if
(
access
(
buf2
,
F_OK
)
==
0
)
{
// Replace everything, mark as leaf
// Replace everything, mark as leaf
node
->
status
|=
IS_MODULE
;
node
->
status
=
IS_MODULE
;
}
else
{
// This will be an intermediate node
node
->
status
=
IS_INTER
;
}
}
}
else
if
(
IS_REG
(
node
))
{
}
else
if
(
IS_REG
(
node
))
{
// This is a leaf, mark as target
// This is a leaf, mark as target
node
->
status
|
=
IS_MODULE
;
node
->
status
=
IS_MODULE
;
}
}
node
=
insert_child
(
parent
,
node
);
node
=
insert_child
(
parent
,
node
);
if
(
IS_DIR
(
node
)
&&
!
(
node
->
status
&
IS_MODULE
)
)
{
if
(
node
->
status
==
IS_INTER
)
{
// Intermediate node, travel deeper
// Intermediate node, travel deeper
construct_tree
(
module
,
node
);
construct_tree
(
module
,
node
);
}
}
...
@@ -325,7 +344,8 @@ static void clone_skeleton(struct node_entry *node) {
...
@@ -325,7 +344,8 @@ static void clone_skeleton(struct node_entry *node) {
// Clone the structure
// Clone the structure
char
*
full_path
=
get_full_path
(
node
);
char
*
full_path
=
get_full_path
(
node
);
if
(
!
(
dir
=
opendir
(
full_path
)))
snprintf
(
buf
,
PATH_MAX
,
"%s%s"
,
MIRRDIR
,
full_path
);
if
(
!
(
dir
=
opendir
(
buf
)))
goto
cleanup
;
goto
cleanup
;
while
((
entry
=
xreaddir
(
dir
)))
{
while
((
entry
=
xreaddir
(
dir
)))
{
if
(
strcmp
(
entry
->
d_name
,
"."
)
==
0
||
strcmp
(
entry
->
d_name
,
".."
)
==
0
)
if
(
strcmp
(
entry
->
d_name
,
"."
)
==
0
||
strcmp
(
entry
->
d_name
,
".."
)
==
0
)
...
@@ -334,7 +354,7 @@ static void clone_skeleton(struct node_entry *node) {
...
@@ -334,7 +354,7 @@ static void clone_skeleton(struct node_entry *node) {
dummy
=
xcalloc
(
sizeof
(
*
dummy
),
1
);
dummy
=
xcalloc
(
sizeof
(
*
dummy
),
1
);
dummy
->
name
=
strdup
(
entry
->
d_name
);
dummy
->
name
=
strdup
(
entry
->
d_name
);
dummy
->
type
=
entry
->
d_type
;
dummy
->
type
=
entry
->
d_type
;
dummy
->
status
|
=
IS_DUMMY
;
dummy
->
status
=
IS_DUMMY
;
insert_child
(
node
,
dummy
);
insert_child
(
node
,
dummy
);
}
}
closedir
(
dir
);
closedir
(
dir
);
...
@@ -342,21 +362,31 @@ static void clone_skeleton(struct node_entry *node) {
...
@@ -342,21 +362,31 @@ static void clone_skeleton(struct node_entry *node) {
snprintf
(
buf
,
PATH_MAX
,
"%s%s"
,
DUMMDIR
,
full_path
);
snprintf
(
buf
,
PATH_MAX
,
"%s%s"
,
DUMMDIR
,
full_path
);
mkdir_p
(
buf
,
0755
);
mkdir_p
(
buf
,
0755
);
clone_attr
(
full_path
,
buf
);
clone_attr
(
full_path
,
buf
);
if
(
node
->
status
&
IS_SKEL
)
bind_mount
(
buf
,
full_path
);
bind_mount
(
buf
,
full_path
);
vec_for_each
(
node
->
children
,
child
)
{
vec_for_each
(
node
->
children
,
child
)
{
snprintf
(
buf
,
PATH_MAX
,
"%s%s/%s"
,
DUMMDIR
,
full_path
,
child
->
name
);
snprintf
(
buf
,
PATH_MAX
,
"%s%s/%s"
,
DUMMDIR
,
full_path
,
child
->
name
);
// Create the dummy file/directory
// Create the dummy file/directory
if
(
IS_DIR
(
child
))
if
(
IS_DIR
(
child
))
x
mkdir
(
buf
,
0755
);
mkdir
(
buf
,
0755
);
else
if
(
IS_REG
(
child
))
else
if
(
IS_REG
(
child
))
close
(
open_new
(
buf
));
close
(
open_new
(
buf
));
// Links will be handled later
if
(
child
->
status
&
IS_MODULE
)
{
if
(
child
->
status
&
IS_VENDOR
)
{
if
(
IS_LNK
(
child
))
{
cp_afc
(
MIRRDIR
"/system/vendor"
,
"/system/vendor"
);
LOGI
(
"cplink: %s -> %s
\n
"
,
MIRRDIR
"/system/vendor"
,
"/system/vendor"
);
}
// Skip
continue
;
}
else
if
(
child
->
status
&
IS_MODULE
)
{
// Mount from module file to dummy file
// Mount from module file to dummy file
snprintf
(
buf2
,
PATH_MAX
,
"%s/%s%s/%s"
,
MOUNTPOINT
,
child
->
module
,
full_path
,
child
->
name
);
snprintf
(
buf2
,
PATH_MAX
,
"%s/%s%s/%s"
,
MOUNTPOINT
,
child
->
module
,
full_path
,
child
->
name
);
}
else
if
(
child
->
status
&
IS_SKEL
)
{
}
else
if
(
child
->
status
&
(
IS_SKEL
|
IS_INTER
)
)
{
// It's a
nother skeleton, recursive call and end
// It's a
intermediate folder, recursive clone
clone_skeleton
(
child
);
clone_skeleton
(
child
);
continue
;
continue
;
}
else
if
(
child
->
status
&
IS_DUMMY
)
{
}
else
if
(
child
->
status
&
IS_DUMMY
)
{
...
@@ -365,11 +395,8 @@ static void clone_skeleton(struct node_entry *node) {
...
@@ -365,11 +395,8 @@ static void clone_skeleton(struct node_entry *node) {
}
}
if
(
IS_LNK
(
child
))
{
if
(
IS_LNK
(
child
))
{
// Symlink special treatments
// Copy symlinks directly
char
*
temp
=
xmalloc
(
PATH_MAX
);
cp_afc
(
buf2
,
buf
);
xreadlink
(
buf2
,
temp
,
PATH_MAX
);
symlink
(
temp
,
buf
);
free
(
temp
);
LOGI
(
"cplink: %s -> %s
\n
"
,
buf2
,
buf
);
LOGI
(
"cplink: %s -> %s
\n
"
,
buf2
,
buf
);
}
else
{
}
else
{
snprintf
(
buf
,
PATH_MAX
,
"%s/%s"
,
full_path
,
child
->
name
);
snprintf
(
buf
,
PATH_MAX
,
"%s/%s"
,
full_path
,
child
->
name
);
...
@@ -385,15 +412,6 @@ static void magic_mount(struct node_entry *node) {
...
@@ -385,15 +412,6 @@ static void magic_mount(struct node_entry *node) {
char
*
real_path
;
char
*
real_path
;
struct
node_entry
*
child
;
struct
node_entry
*
child
;
if
(
strcmp
(
node
->
name
,
"vendor"
)
==
0
&&
strcmp
(
node
->
parent
->
name
,
"/system"
)
==
0
)
{
snprintf
(
buf
,
PATH_MAX
,
"%s/%s/system/vendor"
,
MOUNTPOINT
,
node
->
module
);
snprintf
(
buf2
,
PATH_MAX
,
"%s/%s/vendor"
,
MOUNTPOINT
,
node
->
module
);
unlink
(
buf2
);
symlink
(
buf
,
buf2
);
return
;
}
if
(
node
->
status
)
{
if
(
node
->
status
&
IS_MODULE
)
{
if
(
node
->
status
&
IS_MODULE
)
{
// The real deal, mount module item
// The real deal, mount module item
real_path
=
get_full_path
(
node
);
real_path
=
get_full_path
(
node
);
...
@@ -403,13 +421,13 @@ static void magic_mount(struct node_entry *node) {
...
@@ -403,13 +421,13 @@ static void magic_mount(struct node_entry *node) {
}
else
if
(
node
->
status
&
IS_SKEL
)
{
}
else
if
(
node
->
status
&
IS_SKEL
)
{
// The node is labeled to be cloned with skeleton, lets do it
// The node is labeled to be cloned with skeleton, lets do it
clone_skeleton
(
node
);
clone_skeleton
(
node
);
}
}
else
if
(
node
->
status
&
IS_INTER
)
{
// We should not see dummies, so no need to handle it here
}
else
{
// It's an intermediate node, travel deeper
// It's an intermediate node, travel deeper
vec_for_each
(
node
->
children
,
child
)
vec_for_each
(
node
->
children
,
child
)
magic_mount
(
child
);
magic_mount
(
child
);
}
}
// The only thing goes here should be vendor placeholder
// There should be no dummies, so don't need to handle it here
}
}
/****************
/****************
...
@@ -584,6 +602,7 @@ void post_fs_data(int client) {
...
@@ -584,6 +602,7 @@ void post_fs_data(int client) {
// Create the system root entry
// Create the system root entry
sys_root
=
xcalloc
(
sizeof
(
*
sys_root
),
1
);
sys_root
=
xcalloc
(
sizeof
(
*
sys_root
),
1
);
sys_root
->
name
=
strdup
(
"/system"
);
sys_root
->
name
=
strdup
(
"/system"
);
sys_root
->
status
=
IS_INTER
;
int
has_modules
=
0
;
int
has_modules
=
0
;
...
@@ -629,6 +648,13 @@ void post_fs_data(int client) {
...
@@ -629,6 +648,13 @@ void post_fs_data(int client) {
// Construct structure
// Construct structure
has_modules
=
1
;
has_modules
=
1
;
LOGI
(
"%s: constructing magic mount structure
\n
"
,
module
);
LOGI
(
"%s: constructing magic mount structure
\n
"
,
module
);
// If /system/vendor exists in module, create a link outside
snprintf
(
buf2
,
PATH_MAX
,
"%s/system/vendor"
,
buf
);
if
(
access
(
buf2
,
F_OK
)
==
0
)
{
snprintf
(
buf
,
PATH_MAX
,
"%s/%s/vendor"
,
MOUNTPOINT
,
module
);
unlink
(
buf
);
symlink
(
buf2
,
buf
);
}
construct_tree
(
module
,
sys_root
);
construct_tree
(
module
,
sys_root
);
}
}
}
}
...
@@ -679,25 +705,30 @@ void post_fs_data(int client) {
...
@@ -679,25 +705,30 @@ void post_fs_data(int client) {
LOGI
(
"link: %s -> %s
\n
"
,
buf
,
buf2
);
LOGI
(
"link: %s -> %s
\n
"
,
buf
,
buf2
);
}
}
// Magic!!
// Extract the vendor node out of system tree and swap with placeholder
magic_mount
(
sys_root
);
// Get the vendor node if exists
vec_for_each
(
sys_root
->
children
,
child
)
{
vec_for_each
(
sys_root
->
children
,
child
)
{
if
(
strcmp
(
child
->
name
,
"vendor"
)
==
0
)
{
if
(
strcmp
(
child
->
name
,
"vendor"
)
==
0
)
{
ven_root
=
child
;
ven_root
=
child
;
free
(
ven_root
->
name
);
child
=
xcalloc
(
sizeof
(
*
child
),
1
);
child
->
type
=
seperate_vendor
?
DT_LNK
:
DT_DIR
;
child
->
parent
=
ven_root
->
parent
;
child
->
name
=
ven_root
->
name
;
child
->
status
=
IS_VENDOR
;
vec_entry
(
sys_root
->
children
)[
_
]
=
child
;
ven_root
->
name
=
strdup
(
"/vendor"
);
ven_root
->
name
=
strdup
(
"/vendor"
);
ven_root
->
parent
=
NULL
;
ven_root
->
parent
=
NULL
;
break
;
break
;
}
}
}
}
if
(
ven_root
)
magic_mount
(
ven_root
);
// Magic!!
magic_mount
(
sys_root
);
if
(
ven_root
)
magic_mount
(
ven_root
);
}
}
// Cleanup memory
// Cleanup memory
destroy_subtree
(
sys_root
);
destroy_subtree
(
sys_root
);
if
(
ven_root
)
destroy_subtree
(
ven_root
);
// Execute module scripts
// Execute module scripts
LOGI
(
"* Running module post-fs-data scripts
\n
"
);
LOGI
(
"* Running module post-fs-data scripts
\n
"
);
...
...
jni/utils/misc.c
View file @
1777d9f7
...
@@ -311,6 +311,7 @@ int cp_afc(const char *source, const char *target) {
...
@@ -311,6 +311,7 @@ int cp_afc(const char *source, const char *target) {
char
buffer
[
PATH_MAX
];
char
buffer
[
PATH_MAX
];
xreadlink
(
source
,
buffer
,
sizeof
(
buffer
));
xreadlink
(
source
,
buffer
,
sizeof
(
buffer
));
xsymlink
(
buffer
,
target
);
xsymlink
(
buffer
,
target
);
lchown
(
target
,
buf
.
st_uid
,
buf
.
st_gid
);
lgetfilecon
(
source
,
&
con
);
lgetfilecon
(
source
,
&
con
);
lsetfilecon
(
target
,
con
);
lsetfilecon
(
target
,
con
);
free
(
con
);
free
(
con
);
...
...
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