@@ -167,57 +167,67 @@ const runAsRootCommands = [
167
167
type RootCmd = ( ...cmd : string [ ] ) => string [ ] ;
168
168
169
169
export async function getRootCommand ( adbClient : Adb . DeviceClient ) : Promise < RootCmd | undefined > {
170
- // Just running 'whoami' doesn't fully check certain tricky cases around how the root commands
171
- // handle multiple arguments etc. Pushing & running this script is an accurate test of which
172
- // root mechanisms will actually work on this device:
173
170
const rootTestScriptPath = `${ ANDROID_TEMP } /htk-root-test.sh` ;
174
- let rootTestCommand = [ 'sh' , rootTestScriptPath ] ;
171
+
175
172
try {
176
- await pushFile ( adbClient , stringAsStream ( `
177
- set -e # Fail on error
178
- whoami # Log the current user name, to confirm if we're root
179
- ` ) , rootTestScriptPath , 0o444 ) ;
180
- } catch ( e ) {
181
- console . log ( `Couldn't write root test script to ${ rootTestScriptPath } ` , e ) ;
182
- // Ok, so we can't write the test script, but let's still test for root via whoami directly,
183
- // because maybe if we get root then that won't be a problem
184
- rootTestCommand = [ 'whoami' ] ;
185
- }
173
+ // Just running 'whoami' doesn't fully check certain tricky cases around how the root commands
174
+ // handle multiple arguments etc. Pushing & running this script is an accurate test of which
175
+ // root mechanisms will actually work on this device:
176
+ let rootTestCommand = [ 'sh' , rootTestScriptPath ] ;
177
+ try {
178
+ await pushFile ( adbClient , stringAsStream ( `
179
+ set -e # Fail on error
180
+ whoami # Log the current user name, to confirm if we're root
181
+ ` ) , rootTestScriptPath , 0o444 ) ;
182
+ } catch ( e ) {
183
+ console . log ( `Couldn't write root test script to ${ rootTestScriptPath } ` , e ) ;
184
+ // Ok, so we can't write the test script, but let's still test for root via whoami directly,
185
+ // because maybe if we get root then that won't be a problem
186
+ rootTestCommand = [ 'whoami' ] ;
187
+ }
186
188
187
- // Run our whoami script with each of the possible root commands
188
- const rootCheckResults = await Promise . all (
189
- runAsRootCommands . map ( ( runAsRoot ) =>
190
- run ( adbClient , runAsRoot ( ...rootTestCommand ) , { timeout : 1000 } ) . catch ( console . log )
191
- . then ( ( whoami ) => ( { cmd : runAsRoot , whoami } ) )
189
+ // Run our whoami script with each of the possible root commands
190
+ const rootCheckResults = await Promise . all (
191
+ runAsRootCommands . map ( ( runAsRoot ) =>
192
+ run ( adbClient , runAsRoot ( ...rootTestCommand ) , { timeout : 1000 } ) . catch ( console . log )
193
+ . then ( ( whoami ) => ( { cmd : runAsRoot , whoami } ) )
194
+ )
192
195
)
193
- )
194
196
195
- // Filter to just commands that successfully printed 'root'
196
- const validRootCommands = rootCheckResults
197
- . filter ( ( result ) => ( result . whoami || '' ) . trim ( ) === 'root' )
198
- . map ( ( result ) => result . cmd ) ;
197
+ // Filter to just commands that successfully printed 'root'
198
+ const validRootCommands = rootCheckResults
199
+ . filter ( ( result ) => ( result . whoami || '' ) . trim ( ) === 'root' )
200
+ . map ( ( result ) => result . cmd ) ;
199
201
200
- if ( validRootCommands . length >= 1 ) return validRootCommands [ 0 ] ;
202
+ if ( validRootCommands . length >= 1 ) return validRootCommands [ 0 ] ;
201
203
202
- // If no explicit root commands are available, try to restart adb in root
203
- // mode instead. If this works, *all* commands will run as root.
204
- // We prefer explicit "su" calls if possible, to limit access & side effects.
205
- await adbClient . root ( ) . catch ( ( e : any ) => {
206
- if ( isErrorLike ( e ) && e . message ?. includes ( "adbd is already running as root" ) ) return ;
207
- else console . log ( e ) ;
208
- } ) ;
204
+ // If no explicit root commands are available, try to restart adb in root
205
+ // mode instead. If this works, *all* commands will run as root.
206
+ // We prefer explicit "su" calls if possible, to limit access & side effects.
207
+ await adbClient . root ( ) . catch ( ( e : any ) => {
208
+ if ( isErrorLike ( e ) && e . message ?. includes ( "adbd is already running as root" ) ) return ;
209
+ else console . log ( e ) ;
210
+ } ) ;
209
211
210
- // Sometimes switching to root can disconnect ADB devices, so double-check
211
- // they're still here, and wait a few seconds for them to come back if not.
212
+ // Sometimes switching to root can disconnect ADB devices, so double-check
213
+ // they're still here, and wait a few seconds for them to come back if not.
212
214
213
- await delay ( 500 ) ; // Wait, since they may not disconnect immediately
214
- const whoami = await waitUntil ( 250 , 10 , ( ) : Promise < string | false > => {
215
- return run ( adbClient , rootTestCommand , { timeout : 1000 } ) . catch ( ( ) => false )
216
- } ) . catch ( console . log ) ;
215
+ await delay ( 500 ) ; // Wait, since they may not disconnect immediately
216
+ const whoami = await waitUntil ( 250 , 10 , ( ) : Promise < string | false > => {
217
+ return run ( adbClient , rootTestCommand , { timeout : 1000 } ) . catch ( ( ) => false )
218
+ } ) . catch ( console . log ) ;
217
219
218
- return ( whoami || '' ) . trim ( ) === 'root'
219
- ? ( ...cmd : string [ ] ) => cmd // All commands now run as root
220
- : undefined ; // Still not root, no luck.
220
+ return ( whoami || '' ) . trim ( ) === 'root'
221
+ ? ( ...cmd : string [ ] ) => cmd // All commands now run as root
222
+ : undefined ; // Still not root, no luck.
223
+ } catch ( e ) {
224
+ console . error ( e ) ;
225
+ reportError ( 'ADB root check crashed' ) ;
226
+ return undefined ;
227
+ } finally {
228
+ // Try to clean up the root test script, just to be tidy
229
+ run ( adbClient , [ 'rm' , '-f' , rootTestScriptPath ] ) . catch ( ( ) => { } ) ;
230
+ }
221
231
}
222
232
223
233
export async function hasCertInstalled (
0 commit comments