1+ #import " DeviceController.h"
2+ #include < spawn.h>
3+ #import < sys/sysctl.h>
4+ #import < Foundation/Foundation.h>
5+ #import < FrontBoardServices/FBSSystemService.h>
6+
7+ @implementation DeviceController
8+
9+ #define POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE 1
10+ extern int posix_spawnattr_set_persona_np (const posix_spawnattr_t * __restrict, uid_t , uint32_t );
11+ extern int posix_spawnattr_set_persona_uid_np (const posix_spawnattr_t * __restrict, uid_t );
12+ extern int posix_spawnattr_set_persona_gid_np (const posix_spawnattr_t * __restrict, uid_t );
13+
14+ - (BOOL ) RebootDevice
15+ {
16+ NSString *path = [[NSBundle mainBundle ] pathForResource: @" RebootRootHelper" ofType: @" " ];
17+
18+ NSArray *args = @[]; // 不需要任何额外参数
19+ NSString *stdOut = nil ;
20+ NSString *stdErr = nil ;
21+
22+ if (path == nil ) {
23+ return NO ;
24+ }
25+
26+ int result = spawnRoot (path, args, &stdOut, &stdErr);
27+ if (result == 0 ) {
28+ return YES ;
29+ }
30+
31+ return NO ;
32+ }
33+
34+ // @See https://github.com/opa334/TrollStore/blob/main/Shared/TSUtil.m#L79
35+ int spawnRoot (NSString * path, NSArray * args, NSString ** stdOut, NSString ** stdErr)
36+ {
37+ NSMutableArray * argsM = args.mutableCopy ?: [NSMutableArray new ];
38+ [argsM insertObject: path atIndex: 0 ];
39+
40+ NSUInteger argCount = [argsM count ];
41+ char **argsC = (char **)malloc ((argCount + 1 ) * sizeof (char *));
42+
43+ for (NSUInteger i = 0 ; i < argCount; i++)
44+ {
45+ argsC[i] = strdup ([[argsM objectAtIndex: i] UTF8String ]);
46+ }
47+ argsC[argCount] = NULL ;
48+
49+ posix_spawnattr_t attr;
50+ posix_spawnattr_init (&attr);
51+
52+ posix_spawnattr_set_persona_np (&attr, 99 , POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE);
53+ posix_spawnattr_set_persona_uid_np (&attr, 0 );
54+ posix_spawnattr_set_persona_gid_np (&attr, 0 );
55+
56+ posix_spawn_file_actions_t action;
57+ posix_spawn_file_actions_init (&action);
58+
59+ int outErr[2 ];
60+ if (stdErr)
61+ {
62+ pipe (outErr);
63+ posix_spawn_file_actions_adddup2 (&action, outErr[1 ], STDERR_FILENO);
64+ posix_spawn_file_actions_addclose (&action, outErr[0 ]);
65+ }
66+
67+ int out[2 ];
68+ if (stdOut)
69+ {
70+ pipe (out);
71+ posix_spawn_file_actions_adddup2 (&action, out[1 ], STDOUT_FILENO);
72+ posix_spawn_file_actions_addclose (&action, out[0 ]);
73+ }
74+
75+ pid_t task_pid;
76+ int status = -200 ;
77+ int spawnError = posix_spawn (&task_pid, [path UTF8String ], &action, &attr, (char * const *)argsC, NULL );
78+ posix_spawnattr_destroy (&attr);
79+ for (NSUInteger i = 0 ; i < argCount; i++)
80+ {
81+ free (argsC[i]);
82+ }
83+ free (argsC);
84+
85+ if (spawnError != 0 )
86+ {
87+ NSLog (@" posix_spawn error %d \n " , spawnError);
88+ return spawnError;
89+ }
90+
91+ __block volatile BOOL _isRunning = YES ;
92+ NSMutableString * outString = [NSMutableString new ];
93+ NSMutableString * errString = [NSMutableString new ];
94+ dispatch_semaphore_t sema = 0 ;
95+ dispatch_queue_t logQueue;
96+ if (stdOut || stdErr)
97+ {
98+ logQueue = dispatch_queue_create (" com.opa334.TrollStore.LogCollector" , NULL );
99+ sema = dispatch_semaphore_create (0 );
100+
101+ int outPipe = out[0 ];
102+ int outErrPipe = outErr[0 ];
103+
104+ __block BOOL outEnabled = (BOOL )stdOut;
105+ __block BOOL errEnabled = (BOOL )stdErr;
106+ dispatch_async (logQueue, ^
107+ {
108+ while (_isRunning)
109+ {
110+ @autoreleasepool
111+ {
112+ if (outEnabled)
113+ {
114+ [outString appendString: getNSStringFromFile (outPipe)];
115+ }
116+ if (errEnabled)
117+ {
118+ [errString appendString: getNSStringFromFile (outErrPipe)];
119+ }
120+ }
121+ }
122+ dispatch_semaphore_signal (sema);
123+ });
124+ }
125+
126+ do
127+ {
128+ if (waitpid (task_pid, &status, 0 ) != -1 ) {
129+ NSLog (@" Child status %d " , WEXITSTATUS (status));
130+ } else
131+ {
132+ perror (" waitpid" );
133+ _isRunning = NO ;
134+ return -222 ;
135+ }
136+ } while (!WIFEXITED (status) && !WIFSIGNALED (status));
137+
138+ _isRunning = NO ;
139+ if (stdOut || stdErr)
140+ {
141+ if (stdOut)
142+ {
143+ close (out[1 ]);
144+ }
145+ if (stdErr)
146+ {
147+ close (outErr[1 ]);
148+ }
149+
150+ // wait for logging queue to finish
151+ dispatch_semaphore_wait (sema, DISPATCH_TIME_FOREVER);
152+
153+ if (stdOut)
154+ {
155+ *stdOut = outString.copy ;
156+ }
157+ if (stdErr)
158+ {
159+ *stdErr = errString.copy ;
160+ }
161+ }
162+
163+ return WEXITSTATUS (status);
164+ }
165+
166+ NSString * getNSStringFromFile (int fd)
167+ {
168+ NSMutableString * ms = [NSMutableString new ];
169+ ssize_t num_read;
170+ char c;
171+ if (!fd_is_valid (fd)) return @" " ;
172+ while ((num_read = read (fd, &c, sizeof (c))))
173+ {
174+ [ms appendString: [NSString stringWithFormat: @" %c " , c]];
175+ if (c == ' \n ' ) break ;
176+ }
177+ return ms.copy ;
178+ }
179+
180+ int fd_is_valid (int fd)
181+ {
182+ return fcntl (fd, F_GETFD) != -1 || errno != EBADF;
183+ }
184+
185+ @end
0 commit comments