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
bb964777
Commit
bb964777
authored
May 08, 2017
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve Magic Mount with proper precedence
parent
543ee797
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
107 additions
and
90 deletions
+107
-90
bootstages.c
jni/daemon/bootstages.c
+104
-90
misc.c
jni/utils/misc.c
+3
-0
No files found.
jni/daemon/bootstages.c
View file @
bb964777
...
@@ -25,14 +25,14 @@ static struct vector module_list;
...
@@ -25,14 +25,14 @@ static struct vector module_list;
* Node structure *
* Node structure *
******************/
******************/
// Precedence: MODULE > SKEL > DUMMY
#define DO_NOTHING 0x0
/* intermediate node */
#define DO_NOTHING 0x0
/* intermediate node */
#define IS_DUMMY 0x1
/* mount from mirror */
#define IS_MODULE 0x1
/* mount from module */
#define IS_SKEL 0x2
/* mount from skeleton */
#define IS_DUMMY 0x2
/* mount from mirror */
#define IS_MODULE 0x4
/* mount from module */
#define IS_SKEL 0x4
/* mount from skeleton */
struct
node_entry
{
struct
node_entry
{
const
char
*
module
;
const
char
*
module
;
/* Only used when status & IS_MODULE */
char
*
name
;
char
*
name
;
uint8_t
type
;
uint8_t
type
;
uint8_t
status
;
uint8_t
status
;
...
@@ -40,6 +40,10 @@ struct node_entry {
...
@@ -40,6 +40,10 @@ struct node_entry {
struct
vector
*
children
;
struct
vector
*
children
;
};
};
#define IS_DIR(n) (n->type == DT_DIR)
#define IS_LNK(n) (n->type == DT_LNK)
#define IS_REG(n) (n->type == DT_REG)
/******************
/******************
* Image handling *
* Image handling *
******************/
******************/
...
@@ -226,15 +230,6 @@ void exec_module_script(const char* stage) {
...
@@ -226,15 +230,6 @@ void exec_module_script(const char* stage) {
* Magic Mount *
* Magic Mount *
***************/
***************/
static
int
hasChild
(
struct
node_entry
*
node
,
const
char
*
name
)
{
struct
node_entry
*
child
;
vec_for_each
(
node
->
children
,
child
)
{
if
(
strcmp
(
child
->
name
,
name
)
==
0
)
return
1
;
}
return
0
;
}
static
char
*
get_full_path
(
struct
node_entry
*
node
)
{
static
char
*
get_full_path
(
struct
node_entry
*
node
)
{
char
buffer
[
PATH_MAX
],
temp
[
PATH_MAX
];
char
buffer
[
PATH_MAX
],
temp
[
PATH_MAX
];
// Concat the paths
// Concat the paths
...
@@ -248,6 +243,14 @@ static char *get_full_path(struct node_entry *node) {
...
@@ -248,6 +243,14 @@ static char *get_full_path(struct node_entry *node) {
return
strdup
(
buffer
);
return
strdup
(
buffer
);
}
}
// Free the node
static
void
destroy_node
(
struct
node_entry
*
node
)
{
free
(
node
->
name
);
vec_destroy
(
node
->
children
);
free
(
node
->
children
);
free
(
node
);
}
// Free the node and all children recursively
// Free the node and all children recursively
static
void
destroy_subtree
(
struct
node_entry
*
node
)
{
static
void
destroy_subtree
(
struct
node_entry
*
node
)
{
// Never free parent, since it shall be freed by themselves
// Never free parent, since it shall be freed by themselves
...
@@ -255,13 +258,11 @@ static void destroy_subtree(struct node_entry *node) {
...
@@ -255,13 +258,11 @@ static void destroy_subtree(struct node_entry *node) {
vec_for_each
(
node
->
children
,
e
)
{
vec_for_each
(
node
->
children
,
e
)
{
destroy_subtree
(
e
);
destroy_subtree
(
e
);
}
}
free
(
node
->
name
);
destroy_node
(
node
);
vec_destroy
(
node
->
children
);
free
(
node
->
children
);
free
(
node
);
}
}
static
void
insert_child
(
struct
node_entry
*
p
,
struct
node_entry
*
c
)
{
// Return the child
static
struct
node_entry
*
insert_child
(
struct
node_entry
*
p
,
struct
node_entry
*
c
)
{
c
->
parent
=
p
;
c
->
parent
=
p
;
if
(
p
->
children
==
NULL
)
{
if
(
p
->
children
==
NULL
)
{
p
->
children
=
xmalloc
(
sizeof
(
struct
vector
));
p
->
children
=
xmalloc
(
sizeof
(
struct
vector
));
...
@@ -270,27 +271,36 @@ static void insert_child(struct node_entry *p, struct node_entry *c) {
...
@@ -270,27 +271,36 @@ static void insert_child(struct node_entry *p, struct node_entry *c) {
struct
node_entry
*
e
;
struct
node_entry
*
e
;
vec_for_each
(
p
->
children
,
e
)
{
vec_for_each
(
p
->
children
,
e
)
{
if
(
strcmp
(
e
->
name
,
c
->
name
)
==
0
)
{
if
(
strcmp
(
e
->
name
,
c
->
name
)
==
0
)
{
// Exist duplicate, replace
// Exist duplicate
c
->
children
=
e
->
children
;
if
(
c
->
status
>
e
->
status
)
{
// Precedence is higher, replace with new node
c
->
children
=
e
->
children
;
// Preserve all children
free
(
e
->
name
);
free
(
e
->
name
);
free
(
e
);
free
(
e
);
vec_entry
(
p
->
children
)[
_
]
=
c
;
vec_entry
(
p
->
children
)[
_
]
=
c
;
return
;
return
c
;
}
else
{
// Free the new entry, return old
destroy_node
(
c
);
return
e
;
}
}
}
}
}
// New entry, push back
// New entry, push back
vec_push_back
(
p
->
children
,
c
);
vec_push_back
(
p
->
children
,
c
);
return
c
;
}
}
static
void
construct_tree
(
const
char
*
module
,
const
char
*
path
,
struct
node_entry
*
parent
)
{
static
void
construct_tree
(
const
char
*
module
,
struct
node_entry
*
parent
)
{
DIR
*
dir
;
DIR
*
dir
;
struct
dirent
*
entry
;
struct
dirent
*
entry
;
struct
node_entry
*
node
;
struct
node_entry
*
node
;
snprintf
(
buf
,
PATH_MAX
,
"%s/%s/%s"
,
MOUNTPOINT
,
module
,
path
);
char
*
parent_path
=
get_full_path
(
parent
);
snprintf
(
buf
,
PATH_MAX
,
"%s/%s%s"
,
MOUNTPOINT
,
module
,
parent_path
);
if
(
!
(
dir
=
opendir
(
buf
)))
if
(
!
(
dir
=
opendir
(
buf
)))
return
;
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
)
...
@@ -300,86 +310,83 @@ static void construct_tree(const char *module, const char *path, struct node_ent
...
@@ -300,86 +310,83 @@ static void construct_tree(const char *module, const char *path, struct node_ent
node
->
module
=
module
;
node
->
module
=
module
;
node
->
name
=
strdup
(
entry
->
d_name
);
node
->
name
=
strdup
(
entry
->
d_name
);
node
->
type
=
entry
->
d_type
;
node
->
type
=
entry
->
d_type
;
insert_child
(
parent
,
node
);
snprintf
(
buf
,
PATH_MAX
,
"%s/%s"
,
parent_path
,
node
->
name
);
char
*
real_path
=
get_full_path
(
node
);
// Check if the entry has a correspond target
// Check if the entry has a correspond target
if
(
entry
->
d_type
==
DT_LNK
||
access
(
real_path
,
F_OK
)
==
-
1
)
{
if
(
IS_LNK
(
node
)
||
access
(
buf
,
F_OK
)
==
-
1
)
{
// Mark the parent folder as a skeleton
// Mark the parent folder as a skeleton
parent
->
status
=
IS_SKEL
;
parent
->
status
|=
IS_SKEL
;
node
->
status
=
IS_MODULE
;
node
->
status
|=
IS_MODULE
;
}
else
{
}
else
if
(
IS_DIR
(
node
))
{
if
(
entry
->
d_type
==
DT_DIR
)
{
// Check if marked as replace
// Check if marked as replace
snprintf
(
buf2
,
PATH_MAX
,
"%s/%s/%s/%s/.replace"
,
MOUNTPOINT
,
module
,
path
,
entry
->
d_name
);
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
{
// Travel deeper
snprintf
(
buf2
,
PATH_MAX
,
"%s/%s"
,
path
,
entry
->
d_name
);
char
*
new_path
=
strdup
(
buf2
);
construct_tree
(
module
,
new_path
,
node
);
free
(
new_path
);
}
}
}
else
if
(
entry
->
d_type
==
DT_REG
)
{
}
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
);
if
(
node
->
status
==
DO_NOTHING
)
{
// Intermediate node, travel deeper
construct_tree
(
module
,
node
);
}
}
free
(
real_path
);
}
}
closedir
(
dir
);
closedir
(
dir
);
cleanup:
free
(
parent_path
);
}
}
static
void
clone_skeleton
(
struct
node_entry
*
node
,
const
char
*
real_path
)
{
static
void
clone_skeleton
(
struct
node_entry
*
node
)
{
DIR
*
dir
;
DIR
*
dir
;
struct
dirent
*
entry
;
struct
dirent
*
entry
;
struct
node_entry
*
dummy
,
*
child
;
struct
node_entry
*
dummy
,
*
child
;
// Clone the structure
// Clone the structure
if
(
!
(
dir
=
opendir
(
real_path
)))
char
*
full_path
=
get_full_path
(
node
);
return
;
if
(
!
(
dir
=
opendir
(
full_path
)))
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
)
continue
;
continue
;
if
(
!
hasChild
(
node
,
entry
->
d_name
))
{
// Create dummy node
// Create dummy 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
);
snprintf
(
buf
,
PATH_MAX
,
"%s%s"
,
DUMMDIR
,
rea
l_path
);
snprintf
(
buf
,
PATH_MAX
,
"%s%s"
,
DUMMDIR
,
ful
l_path
);
mkdir_p
(
buf
,
0755
);
mkdir_p
(
buf
,
0755
);
clone_attr
(
rea
l_path
,
buf
);
clone_attr
(
ful
l_path
,
buf
);
bind_mount
(
buf
,
rea
l_path
);
bind_mount
(
buf
,
ful
l_path
);
vec_for_each
(
node
->
children
,
child
)
{
vec_for_each
(
node
->
children
,
child
)
{
snprintf
(
buf
,
PATH_MAX
,
"%s%s/%s"
,
DUMMDIR
,
real_path
,
child
->
name
);
snprintf
(
buf
,
PATH_MAX
,
"%s%s/%s"
,
DUMMDIR
,
full_path
,
child
->
name
);
if
(
child
->
type
==
DT_DIR
)
{
// Create the dummy file/directory
if
(
IS_DIR
(
child
))
xmkdir
(
buf
,
0755
);
xmkdir
(
buf
,
0755
);
}
else
if
(
child
->
type
==
DT_REG
)
{
else
if
(
IS_REG
(
child
))
close
(
open_new
(
buf
));
close
(
open_new
(
buf
));
}
if
(
child
->
status
==
IS_MODULE
)
{
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
,
real_path
,
child
->
name
);
snprintf
(
buf2
,
PATH_MAX
,
"%s/%s%s/%s"
,
MOUNTPOINT
,
child
->
module
,
full_path
,
child
->
name
);
}
else
if
(
child
->
status
==
IS_DUMMY
)
{
}
else
if
(
child
->
status
&
IS_SKEL
)
{
// Mount from mirror to dummy file
snprintf
(
buf2
,
PATH_MAX
,
"%s%s/%s"
,
MIRRDIR
,
real_path
,
child
->
name
);
}
else
if
(
child
->
status
==
IS_SKEL
)
{
// It's another skeleton, recursive call and end
// It's another skeleton, recursive call and end
char
*
s
=
get_full_path
(
child
);
clone_skeleton
(
child
);
clone_skeleton
(
child
,
s
);
free
(
s
);
continue
;
continue
;
}
else
if
(
child
->
status
&
IS_DUMMY
)
{
// Mount from mirror to dummy file
snprintf
(
buf2
,
PATH_MAX
,
"%s%s/%s"
,
MIRRDIR
,
full_path
,
child
->
name
);
}
}
if
(
child
->
type
==
DT_LNK
)
{
if
(
IS_LNK
(
child
))
{
// Symlink special treatments
// Symlink special treatments
char
*
temp
=
xmalloc
(
PATH_MAX
);
char
*
temp
=
xmalloc
(
PATH_MAX
);
xreadlink
(
buf2
,
temp
,
PATH_MAX
);
xreadlink
(
buf2
,
temp
,
PATH_MAX
);
...
@@ -387,10 +394,13 @@ static void clone_skeleton(struct node_entry *node, const char *real_path) {
...
@@ -387,10 +394,13 @@ static void clone_skeleton(struct node_entry *node, const char *real_path) {
free
(
temp
);
free
(
temp
);
LOGI
(
"cplink: %s -> %s
\n
"
,
buf2
,
buf
);
LOGI
(
"cplink: %s -> %s
\n
"
,
buf2
,
buf
);
}
else
{
}
else
{
snprintf
(
buf
,
PATH_MAX
,
"%s/%s"
,
rea
l_path
,
child
->
name
);
snprintf
(
buf
,
PATH_MAX
,
"%s/%s"
,
ful
l_path
,
child
->
name
);
bind_mount
(
buf2
,
buf
);
bind_mount
(
buf2
,
buf
);
}
}
}
}
cleanup:
free
(
full_path
);
}
}
static
void
magic_mount
(
struct
node_entry
*
node
)
{
static
void
magic_mount
(
struct
node_entry
*
node
)
{
...
@@ -405,18 +415,22 @@ static void magic_mount(struct node_entry *node) {
...
@@ -405,18 +415,22 @@ static void magic_mount(struct node_entry *node) {
return
;
return
;
}
}
if
(
node
->
status
==
DO_NOTHING
)
{
if
(
node
->
status
)
{
vec_for_each
(
node
->
children
,
child
)
if
(
node
->
status
&
IS_MODULE
)
{
magic_mount
(
child
);
// The real deal, mount module item
}
else
{
real_path
=
get_full_path
(
node
);
real_path
=
get_full_path
(
node
);
if
(
node
->
status
==
IS_MODULE
)
{
snprintf
(
buf
,
PATH_MAX
,
"%s/%s%s"
,
MOUNTPOINT
,
node
->
module
,
real_path
);
snprintf
(
buf
,
PATH_MAX
,
"%s/%s%s"
,
MOUNTPOINT
,
node
->
module
,
real_path
);
bind_mount
(
buf
,
real_path
);
bind_mount
(
buf
,
real_path
);
}
else
if
(
node
->
status
==
IS_SKEL
)
{
clone_skeleton
(
node
,
real_path
);
}
free
(
real_path
);
free
(
real_path
);
}
else
if
(
node
->
status
&
IS_SKEL
)
{
// The node is labeled to be cloned with skeleton, lets do it
clone_skeleton
(
node
);
}
// We should not see dummies, so no need to handle it here
}
else
{
// It's an intermediate node, travel deeper
vec_for_each
(
node
->
children
,
child
)
magic_mount
(
child
);
}
}
}
}
...
@@ -599,7 +613,7 @@ void post_fs_data(int client) {
...
@@ -599,7 +613,7 @@ 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
);
construct_tree
(
module
,
"system"
,
sys_root
);
construct_tree
(
module
,
sys_root
);
}
}
}
}
...
...
jni/utils/misc.c
View file @
bb964777
...
@@ -267,8 +267,11 @@ int mkdir_p(const char *pathname, mode_t mode) {
...
@@ -267,8 +267,11 @@ int mkdir_p(const char *pathname, mode_t mode) {
int
bind_mount
(
const
char
*
from
,
const
char
*
to
)
{
int
bind_mount
(
const
char
*
from
,
const
char
*
to
)
{
int
ret
=
xmount
(
from
,
to
,
NULL
,
MS_BIND
,
NULL
);
int
ret
=
xmount
(
from
,
to
,
NULL
,
MS_BIND
,
NULL
);
#ifdef DEBUG
LOGD
(
"bind_mount: %s -> %s
\n
"
,
from
,
to
);
LOGD
(
"bind_mount: %s -> %s
\n
"
,
from
,
to
);
#else
LOGI
(
"bind_mount: %s
\n
"
,
to
);
LOGI
(
"bind_mount: %s
\n
"
,
to
);
#endif
return
ret
;
return
ret
;
}
}
...
...
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