@@ -170,34 +170,34 @@ export async function getRootCommand(adbClient: Adb.DeviceClient): Promise<RootC
170
170
const rootTestScriptPath = `${ ANDROID_TEMP } /htk-root-test.sh` ;
171
171
172
172
try {
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:
173
+ // Just running 'id ' doesn't fully check certain tricky cases around how the root commands handle
174
+ // multiple arguments etc. N.b. whoami also doesn't exist on older devices. Pushing & running
175
+ // this script is an accurate test of which root mechanisms will actually work on this device:
176
176
let rootTestCommand = [ 'sh' , rootTestScriptPath ] ;
177
177
try {
178
178
await pushFile ( adbClient , stringAsStream ( `
179
179
set -e # Fail on error
180
- whoami # Log the current user name , to confirm if we're root
180
+ id # Log the current user details , to confirm if we're root
181
181
` ) , rootTestScriptPath , 0o444 ) ;
182
182
} catch ( e ) {
183
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,
184
+ // Ok, so we can't write the test script, but let's still test for root directly,
185
185
// because maybe if we get root then that won't be a problem
186
- rootTestCommand = [ 'whoami ' ] ;
186
+ rootTestCommand = [ 'id ' ] ;
187
187
}
188
188
189
- // Run our whoami script with each of the possible root commands
189
+ // Run our root test script with each of the possible root commands
190
190
const rootCheckResults = await Promise . all (
191
191
runAsRootCommands . map ( ( runAsRoot ) =>
192
192
run ( adbClient , runAsRoot ( ...rootTestCommand ) , { timeout : 1000 } )
193
193
. catch ( ( e : any ) => console . log ( e . message ?? e ) )
194
- . then ( ( whoami ) => ( { cmd : runAsRoot , whoami } ) )
194
+ . then ( ( result ) => ( { cmd : runAsRoot , result } ) )
195
195
)
196
196
)
197
197
198
- // Filter to just commands that successfully printed 'root'
198
+ // Filter to just commands that successfully printed 'uid=0( root) '
199
199
const validRootCommands = rootCheckResults
200
- . filter ( ( result ) => ( result . whoami || '' ) . trim ( ) === ' root' )
200
+ . filter ( ( result ) => ( result . result || '' ) . includes ( 'uid=0( root)' ) )
201
201
. map ( ( result ) => result . cmd ) ;
202
202
203
203
if ( validRootCommands . length >= 1 ) return validRootCommands [ 0 ] ;
@@ -214,11 +214,11 @@ export async function getRootCommand(adbClient: Adb.DeviceClient): Promise<RootC
214
214
// they're still here, and wait a few seconds for them to come back if not.
215
215
216
216
await delay ( 500 ) ; // Wait, since they may not disconnect immediately
217
- const whoami = await waitUntil ( 250 , 10 , ( ) : Promise < string | false > => {
217
+ const idResult = await waitUntil ( 250 , 10 , ( ) : Promise < string | false > => {
218
218
return run ( adbClient , rootTestCommand , { timeout : 1000 } ) . catch ( ( ) => false )
219
219
} ) . catch ( console . log ) ;
220
220
221
- return ( whoami || '' ) . trim ( ) === ' root'
221
+ return ( idResult || '' ) . includes ( 'uid=0( root)' )
222
222
? ( ...cmd : string [ ] ) => cmd // All commands now run as root
223
223
: undefined ; // Still not root, no luck.
224
224
} catch ( e ) {
0 commit comments