11#!/data/data/com.tool.tree/files/home/termux/bin/python
2-
32# -*- coding: utf-8 -*-
3+
44import os
55import sys
6- from re import sub
7- from re import escape
86
7+ # Đồng bộ kiểu dữ liệu mảng [list] để không bị lỗi rã chữ cái khi dùng join()
8+ # Đã điều chỉnh key không có dấu "/" ở đầu để khớp hoàn chỉnh với cấu trúc sinh ra từ scan_dir
99fix_permission = {
10- "/vendor/bin/hw/android.hardware.wifi@1.0" : "u:object_r:hal_wifi_default_exec:s0"
10+ "vendor/bin/hw/android.hardware.wifi@1.0" : ["u:object_r:hal_wifi_default_exec:s0" ],
11+ "system/bin/init" : ["u:object_r:init_exec:s0" ],
12+ "lost+found" : ["u:object_r:rootfs:s0" ],
13+ "system/bin/idmap" : ["u:object_r:idmap_exec:s0" ],
14+ "system/bin/fsck" : ["u:object_r:fsck_exec:s0" ],
15+ "system/bin/e2fsck" : ["u:object_r:fsck_exec:s0" ],
16+ "system/bin/logcat" : ["u:object_r:logcat_exec:s0" ]
1117}
1218
13- def str_to_selinux (s : str ) -> str :
14- return escape (s ).replace ('\\ -' , '-' )
15-
16- def scan_context (file ) -> dict :
19+ def scan_context (file ) -> tuple :
20+ """Đọc file context, giữ nguyên cấu trúc Regex gốc và bảo toàn thứ tự dòng."""
1721 context = {}
22+ original_order = []
23+
1824 with open (file , "r" , encoding = 'utf-8' ) as file_ :
19- for i in file_ .readlines ():
20- line = i .strip ().replace ('\\ ' , '' )
21- if not line :
22- continue
23- if line .startswith ('#' ):
25+ for i in file_ :
26+ line = i .strip ()
27+ if not line or line .startswith ('#' ):
2428 continue
29+
2530 parts = line .split ()
2631 if not parts :
2732 continue
33+
2834 filepath , * other = parts
2935 filepath = filepath .replace (r'\@' , '@' )
3036 context [filepath ] = other
31- return context
37+ original_order .append (filepath )
38+
39+ return context , original_order
3240
3341def scan_dir (folder ) -> list :
34- part_name = os .path .basename (folder )
42+ """
43+ Quét thư mục thực tế và chuyển đổi sang định dạng path chuẩn của Android.
44+ HỖ TRỢ DYNAMIC PARTITIONS: Tự động đưa tên thư mục tạm về tên phân vùng chuẩn.
45+ """
46+ # Lấy tên thư mục gốc (giữ nguyên hoa/thường để tránh lỗi phân vùng tùy biến)
47+ folder_name_raw = os .path .basename (os .path .normpath (folder ))
48+ folder_name = folder_name_raw .lower ()
49+
50+ # Mặc định là tên thư mục gốc ban đầu nếu không nhận diện được phân vùng chuẩn
51+ part_name = folder_name_raw
52+ for partition in ['vendor' , 'product' , 'system_ext' , 'odm' , 'system' ]:
53+ if partition in folder_name :
54+ part_name = partition
55+ break
56+
57+ # Xây dựng các root path chuẩn (SELinux của Android thường viết dạng /vendor hay /vendor/.*)
3558 allfiles = ['/' , f'/{ part_name } /lost+found' , f'/{ part_name } ' , f'/{ part_name } /' ]
59+
3660 for root , dirs , files in os .walk (folder , topdown = True ):
3761 for dir_ in dirs :
3862 if os .name == 'nt' :
@@ -44,51 +68,71 @@ def scan_dir(folder) -> list:
4468 allfiles .append (os .path .join (root , file ).replace (folder , '/' + part_name ).replace ('\\ ' , '/' ))
4569 elif os .name == 'posix' :
4670 allfiles .append (os .path .join (root , file ).replace (folder , '/' + part_name ))
71+
4772 return sorted (set (allfiles ), key = allfiles .index )
4873
49-
50- def context_patch ( fs_file , filename ) -> dict :
74+ def context_patch ( fs_file , filename ) -> tuple :
75+ """Vá context thông minh dựa trên luật cứng hoặc thừa kế từ thư mục cha."""
5176 new_fs = {}
52- # Giữ logic cũ: lấy permission mặc định từ entry đầu
53- permission_d = fs_file .get (next (iter (fs_file )))
54- if not permission_d :
55- permission_d = ['u:object_r:system_file:s0' ]
77+ added_keys = []
78+
79+ permission_d = ['u:object_r:system_file:s0' ]
80+ if fs_file :
81+ permission_d = fs_file .get (next (iter (fs_file )), permission_d )
82+
5683 for i in filename :
57- selinux_path = str_to_selinux (i )
58- if fs_file .get (i ):
59- new_fs [selinux_path ] = fs_file [i ]
84+ actual_i = i if i .isprintable () else '' .join (c if c .isprintable () else '*' for c in i )
85+
86+ if fs_file .get (actual_i ):
87+ new_fs [actual_i ] = fs_file [actual_i ]
6088 continue
89+
90+ if actual_i in new_fs :
91+ continue
92+
6193 permission = permission_d
62- if i :
63- # giữ logic cũ: thay ký tự không printable bằng '*'
64- if not i .isprintable ():
65- i = '' .join (c if c .isprintable () else '*' for c in i )
66- # giữ logic cũ: fix_permission
67- if i in fix_permission :
68- permission = fix_permission [i ]
69- else :
70- # giữ nguyên logic tìm thư mục cha
71- tmp_path = os .path .dirname (i )
72- while tmp_path and tmp_path != "/" :
73- if tmp_path in fs_file :
74- permission = fs_file [tmp_path ]
75- break
76- tmp_path = os .path .dirname (tmp_path )
77- print (f"ADD [{ i } :{ permission } ]" )
78- new_fs [selinux_path ] = permission
79- return new_fs
94+
95+ # Đồng bộ hóa việc check luật cứng (loại bỏ dấu "/" ở đầu actual_i nếu có để khớp fix_permission)
96+ clean_i = actual_i .lstrip ('/' )
97+
98+ if clean_i in fix_permission :
99+ permission = fix_permission [clean_i ]
100+ elif actual_i in fix_permission :
101+ permission = fix_permission [actual_i ]
102+ else :
103+ # Thuật toán tìm ngược lên thư mục cha để lấy quyền kế thừa
104+ tmp_path = os .path .dirname (actual_i )
105+ while tmp_path and tmp_path != "/" :
106+ if tmp_path in fs_file :
107+ permission = fs_file [tmp_path ]
108+ break
109+ tmp_path = os .path .dirname (tmp_path )
80110
111+ print (f"ADD [{ actual_i } :{ permission } ]" )
112+ new_fs [actual_i ] = permission
113+ added_keys .append (actual_i )
114+
115+ return new_fs , added_keys
81116
82117def main (dir_path , fs_config ) -> None :
83- origin = scan_context (os .path .abspath (fs_config ))
118+ origin , orig_order = scan_context (os .path .abspath (fs_config ))
84119 allfiles = scan_dir (os .path .abspath (dir_path ))
85- new_fs = context_patch (origin , allfiles )
86- with open (fs_config , "w+" , encoding = 'utf-8' , newline = '\n ' ) as f :
87- f .writelines ([i + " " + " " .join (new_fs [i ]) + "\n " for i in sorted (new_fs .keys ())])
88- print ("Load origin %d" % (len (origin .keys ())) + " entries" )
89- print ("Detect total %d" % (len (allfiles )) + " entries" )
90- print ('Add %d' % (len (new_fs .keys ()) - len (origin .keys ())) + " entries" )
120+
121+ new_fs , added_keys = context_patch (origin , allfiles )
122+
123+ with open (fs_config , "w" , encoding = 'utf-8' , newline = '\n ' ) as f :
124+ for key in orig_order :
125+ if key in new_fs :
126+ f .write (f"{ key } { ' ' .join (new_fs [key ])} \n " )
127+ del new_fs [key ]
128+
129+ for key in sorted (added_keys ):
130+ if key in new_fs :
131+ f .write (f"{ key } { ' ' .join (new_fs [key ])} \n " )
91132
133+ print ("Load origin %d entries" % (len (origin .keys ())))
134+ print ("Detect total %d entries" % (len (allfiles )))
135+ print ("Add %d entries thành công" % (len (added_keys )))
92136
93137if __name__ == "__main__" :
94138 if len (sys .argv ) < 3 :
@@ -97,5 +141,4 @@ def main(dir_path, fs_config) -> None:
97141 if not os .path .exists (sys .argv [1 ]) or not os .path .exists (sys .argv [2 ]):
98142 print ("File does not exist" )
99143 sys .exit (1 )
100- main (sys .argv [1 ], sys .argv [2 ])
101-
144+ main (sys .argv [1 ], sys .argv [2 ])
0 commit comments