@@ -269,11 +269,11 @@ impl Command {
269
269
None
270
270
} ;
271
271
let program = resolve_exe ( & self . program , || env:: var_os ( "PATH" ) , child_paths) ?;
272
- let is_batch_file = program
273
- . extension ( )
274
- . map ( |ext| ext . eq_ignore_ascii_case ( "cmd" ) || ext . eq_ignore_ascii_case ( "bat" ) )
275
- . unwrap_or ( false ) ;
276
- let program = path :: maybe_verbatim ( & program ) ? ;
272
+ // Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd"
273
+ let is_batch_file = matches ! (
274
+ program . len ( ) . checked_sub ( 5 ) . and_then ( |i| program . get ( i.. ) ) ,
275
+ Some ( [ 46 , 98 | 66 , 97 | 65 , 116 | 84 , 0 ] | [ 46 , 99 | 67 , 109 | 77 , 100 | 68 , 0 ] )
276
+ ) ;
277
277
let mut cmd_str =
278
278
make_command_line ( & program, & self . args , self . force_quotes_enabled , is_batch_file) ?;
279
279
cmd_str. push ( 0 ) ; // add null terminator
@@ -370,7 +370,7 @@ fn resolve_exe<'a>(
370
370
exe_path : & ' a OsStr ,
371
371
parent_paths : impl FnOnce ( ) -> Option < OsString > ,
372
372
child_paths : Option < & OsStr > ,
373
- ) -> io:: Result < PathBuf > {
373
+ ) -> io:: Result < Vec < u16 > > {
374
374
// Early return if there is no filename.
375
375
if exe_path. is_empty ( ) || path:: has_trailing_slash ( exe_path) {
376
376
return Err ( io:: const_io_error!(
@@ -392,19 +392,19 @@ fn resolve_exe<'a>(
392
392
if has_exe_suffix {
393
393
// The application name is a path to a `.exe` file.
394
394
// Let `CreateProcessW` figure out if it exists or not.
395
- return Ok ( exe_path . into ( ) ) ;
395
+ return path :: maybe_verbatim ( Path :: new ( exe_path ) ) ;
396
396
}
397
397
let mut path = PathBuf :: from ( exe_path) ;
398
398
399
399
// Append `.exe` if not already there.
400
400
path = path:: append_suffix ( path, EXE_SUFFIX . as_ref ( ) ) ;
401
- if program_exists ( & path) {
401
+ if let Some ( path ) = program_exists ( & path) {
402
402
return Ok ( path) ;
403
403
} else {
404
404
// It's ok to use `set_extension` here because the intent is to
405
405
// remove the extension that was just added.
406
406
path. set_extension ( "" ) ;
407
- return Ok ( path) ;
407
+ return path :: maybe_verbatim ( & path) ;
408
408
}
409
409
} else {
410
410
ensure_no_nuls ( exe_path) ?;
@@ -419,7 +419,7 @@ fn resolve_exe<'a>(
419
419
if !has_extension {
420
420
path. set_extension ( EXE_EXTENSION ) ;
421
421
}
422
- if program_exists ( & path) { Some ( path ) } else { None }
422
+ program_exists ( & path)
423
423
} ) ;
424
424
if let Some ( path) = result {
425
425
return Ok ( path) ;
@@ -435,10 +435,10 @@ fn search_paths<Paths, Exists>(
435
435
parent_paths : Paths ,
436
436
child_paths : Option < & OsStr > ,
437
437
mut exists : Exists ,
438
- ) -> Option < PathBuf >
438
+ ) -> Option < Vec < u16 > >
439
439
where
440
440
Paths : FnOnce ( ) -> Option < OsString > ,
441
- Exists : FnMut ( PathBuf ) -> Option < PathBuf > ,
441
+ Exists : FnMut ( PathBuf ) -> Option < Vec < u16 > > ,
442
442
{
443
443
// 1. Child paths
444
444
// This is for consistency with Rust's historic behaviour.
@@ -490,17 +490,18 @@ where
490
490
}
491
491
492
492
/// Check if a file exists without following symlinks.
493
- fn program_exists ( path : & Path ) -> bool {
493
+ fn program_exists ( path : & Path ) -> Option < Vec < u16 > > {
494
494
unsafe {
495
- to_u16s ( path)
496
- . map ( |path| {
497
- // Getting attributes using `GetFileAttributesW` does not follow symlinks
498
- // and it will almost always be successful if the link exists.
499
- // There are some exceptions for special system files (e.g. the pagefile)
500
- // but these are not executable.
501
- c:: GetFileAttributesW ( path. as_ptr ( ) ) != c:: INVALID_FILE_ATTRIBUTES
502
- } )
503
- . unwrap_or ( false )
495
+ let path = path:: maybe_verbatim ( path) . ok ( ) ?;
496
+ // Getting attributes using `GetFileAttributesW` does not follow symlinks
497
+ // and it will almost always be successful if the link exists.
498
+ // There are some exceptions for special system files (e.g. the pagefile)
499
+ // but these are not executable.
500
+ if c:: GetFileAttributesW ( path. as_ptr ( ) ) == c:: INVALID_FILE_ATTRIBUTES {
501
+ None
502
+ } else {
503
+ Some ( path)
504
+ }
504
505
}
505
506
}
506
507
0 commit comments