1+ #include <stdint.h>
2+ #include <stddef.h>
3+ #include <dispatch/dispatch.h>
4+ #include <dlfcn.h>
5+ #include <sys/param.h>
6+ #include <stdlib.h>
7+ #include <string.h>
8+
9+ #include <libroot.h>
10+
11+ #if THEOS_PACKAGE_SCHEME_ROOTHIDE
12+ #include <roothide.h>
13+ #endif
14+
15+ static const char * (* dyn_get_root_prefix )(void ) = NULL ;
16+ static const char * (* dyn_get_jbroot_prefix )(void ) = NULL ;
17+ static const char * (* dyn_get_boot_uuid )(void ) = NULL ;
18+ static char * (* dyn_jbrootpath )(const char * path , char * resolvedPath ) = NULL ;
19+ static char * (* dyn_rootfspath )(const char * path , char * resolvedPath ) = NULL ;
20+
21+ #if TARGET_OS_SIMULATOR
22+
23+ static const char * libroot_get_root_prefix_fallback (void )
24+ {
25+ return IPHONE_SIMULATOR_ROOT ;
26+ }
27+
28+ static const char * libroot_get_jbroot_prefix_fallback (void )
29+ {
30+ return IPHONE_SIMULATOR_ROOT ;
31+ }
32+
33+ #else
34+
35+ #if THEOS_PACKAGE_SCHEME_ROOTHIDE
36+
37+ static const char * libroot_get_root_prefix_fallback (void )
38+ {
39+ return rootfs ("/" );
40+ }
41+
42+ static const char * libroot_get_jbroot_prefix_fallback (void )
43+ {
44+ return jbroot ("/" );
45+ }
46+
47+ #else
48+
49+ #if IPHONEOS_ARM64
50+
51+ static const char * libroot_get_root_prefix_fallback (void )
52+ {
53+ return "" ;
54+ }
55+
56+ static const char * libroot_get_jbroot_prefix_fallback (void )
57+ {
58+ return "/var/jb" ;
59+ }
60+
61+ #else
62+
63+ static const char * libroot_get_root_prefix_fallback (void )
64+ {
65+ return "" ;
66+ }
67+
68+ static const char * libroot_get_jbroot_prefix_fallback (void )
69+ {
70+ if (access ("/var/LIY" , F_OK ) == 0 ) {
71+ // Legacy support for XinaA15 1.x (For those two people still using it)
72+ // Technically this should be deprecated, but with the libroot solution it's not the hardest thing in the world to maintain
73+ // So I decided to leave it in
74+ return "/var/jb" ;
75+ }
76+ else {
77+ return "" ;
78+ }
79+ }
80+
81+ #endif
82+ #endif
83+ #endif
84+
85+ static const char * libroot_get_boot_uuid_fallback (void )
86+ {
87+ return "00000000-0000-0000-0000-000000000000" ;
88+ }
89+
90+ static char * libroot_rootfspath_fallback (const char * path , char * resolvedPath )
91+ {
92+ if (!path ) return NULL ;
93+ if (!resolvedPath ) resolvedPath = malloc (PATH_MAX );
94+
95+ const char * prefix = libroot_dyn_get_root_prefix ();
96+ const char * jbRootPrefix = libroot_dyn_get_jbroot_prefix ();
97+ size_t jbRootPrefixLen = strlen (jbRootPrefix );
98+
99+ if (path [0 ] == '/' ) {
100+ // This function has two different purposes
101+ // If what we have is a subpath of the jailbreak root, strip the jailbreak root prefix
102+ // Else, add the rootfs prefix
103+ if (!strncmp (path , jbRootPrefix , jbRootPrefixLen )) {
104+ strlcpy (resolvedPath , & path [jbRootPrefixLen ], PATH_MAX );
105+ }
106+ else {
107+ strlcpy (resolvedPath , prefix , PATH_MAX );
108+ strlcat (resolvedPath , path , PATH_MAX );
109+ }
110+ }
111+ else {
112+ // Don't modify relative paths
113+ strlcpy (resolvedPath , path , PATH_MAX );
114+ }
115+
116+ return resolvedPath ;
117+ }
118+
119+ static char * libroot_jbrootpath_fallback (const char * path , char * resolvedPath )
120+ {
121+ if (!path ) return NULL ;
122+ if (!resolvedPath ) resolvedPath = malloc (PATH_MAX );
123+
124+ const char * prefix = libroot_dyn_get_jbroot_prefix ();
125+ bool skipRedirection = path [0 ] != '/' ; // Don't redirect relative paths
126+
127+ #ifndef IPHONEOS_ARM64
128+ // Special case
129+ // On XinaA15 v1: Don't redirect /var/mobile paths to /var/jb/var/mobile
130+ if (!skipRedirection ) {
131+ if (access ("/var/LIY" , F_OK ) == 0 ) {
132+ skipRedirection = strncmp (path , "/var/mobile" , 11 ) == 0 ;
133+ }
134+ }
135+ #endif
136+
137+ if (!skipRedirection ) {
138+ strlcpy (resolvedPath , prefix , PATH_MAX );
139+ strlcat (resolvedPath , path , PATH_MAX );
140+ }
141+ else {
142+ strlcpy (resolvedPath , path , PATH_MAX );
143+ }
144+
145+ return resolvedPath ;
146+ }
147+
148+ static void libroot_load (void )
149+ {
150+ static dispatch_once_t onceToken ;
151+ dispatch_once (& onceToken , ^{
152+ void * handle = dlopen ("@rpath/libroot.dylib" , RTLD_NOW );
153+ if (handle ) {
154+ dyn_get_root_prefix = dlsym (handle , "libroot_get_root_prefix" );
155+ dyn_get_jbroot_prefix = dlsym (handle , "libroot_get_jbroot_prefix" );
156+ dyn_get_boot_uuid = dlsym (handle , "libroot_get_boot_uuid" );
157+ dyn_jbrootpath = dlsym (handle , "libroot_jbrootpath" );
158+ dyn_rootfspath = dlsym (handle , "libroot_rootfspath" );
159+ }
160+ if (!dyn_get_root_prefix ) dyn_get_root_prefix = libroot_get_root_prefix_fallback ;
161+ if (!dyn_get_jbroot_prefix ) dyn_get_jbroot_prefix = libroot_get_jbroot_prefix_fallback ;
162+ if (!dyn_get_boot_uuid ) dyn_get_boot_uuid = libroot_get_boot_uuid_fallback ;
163+ if (!dyn_jbrootpath ) dyn_jbrootpath = libroot_jbrootpath_fallback ;
164+ if (!dyn_rootfspath ) dyn_rootfspath = libroot_rootfspath_fallback ;
165+ });
166+ }
167+
168+ const char * libroot_dyn_get_root_prefix (void )
169+ {
170+ libroot_load ();
171+ return dyn_get_root_prefix ();
172+ }
173+
174+ const char * libroot_dyn_get_jbroot_prefix (void )
175+ {
176+ libroot_load ();
177+ return dyn_get_jbroot_prefix ();
178+ }
179+
180+ const char * libroot_dyn_get_boot_uuid (void )
181+ {
182+ libroot_load ();
183+ return dyn_get_boot_uuid ();
184+ }
185+
186+ char * libroot_dyn_rootfspath (const char * path , char * resolvedPath )
187+ {
188+ libroot_load ();
189+ return dyn_rootfspath (path , resolvedPath );
190+ }
191+
192+ char * libroot_dyn_jbrootpath (const char * path , char * resolvedPath )
193+ {
194+ libroot_load ();
195+ return dyn_jbrootpath (path , resolvedPath );
196+ }
0 commit comments