@@ -167,57 +167,67 @@ const runAsRootCommands = [
167167type RootCmd = ( ...cmd : string [ ] ) => string [ ] ;
168168
169169export 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:
173170 const rootTestScriptPath = `${ ANDROID_TEMP } /htk-root-test.sh` ;
174- let rootTestCommand = [ 'sh' , rootTestScriptPath ] ;
171+
175172 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+ }
186188
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+ )
192195 )
193- )
194196
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 ) ;
199201
200- if ( validRootCommands . length >= 1 ) return validRootCommands [ 0 ] ;
202+ if ( validRootCommands . length >= 1 ) return validRootCommands [ 0 ] ;
201203
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+ } ) ;
209211
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.
212214
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 ) ;
217219
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+ }
221231}
222232
223233export async function hasCertInstalled (
0 commit comments