1
1
use std:: ffi:: { OsStr , OsString } ;
2
- use std:: path:: Path ;
2
+ use std:: path:: { Path , PathBuf } ;
3
3
use std:: { iter, mem} ;
4
4
use std:: convert:: TryFrom ;
5
5
use std:: borrow:: Cow ;
6
6
7
+ #[ cfg( unix) ]
8
+ use std:: os:: unix:: ffi:: { OsStrExt , OsStringExt } ;
9
+ #[ cfg( windows) ]
10
+ use std:: os:: windows:: ffi:: { OsStrExt , OsStringExt } ;
11
+
7
12
use rustc:: mir;
8
13
use rustc:: ty:: {
9
14
self ,
@@ -479,7 +484,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
479
484
{
480
485
#[ cfg( unix) ]
481
486
fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
482
- Ok ( std :: os :: unix :: ffi :: OsStrExt :: from_bytes ( bytes) )
487
+ Ok ( OsStr :: from_bytes ( bytes) )
483
488
}
484
489
#[ cfg( not( unix) ) ]
485
490
fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
@@ -499,8 +504,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
499
504
' tcx : ' a ,
500
505
' mir : ' a ,
501
506
{
502
- let os_str = self . read_os_str_from_c_str ( scalar) ?;
503
- Ok ( Cow :: Borrowed ( Path :: new ( os_str) ) )
507
+ let this = self . eval_context_ref ( ) ;
508
+ let os_str = this. read_os_str_from_c_str ( scalar) ?;
509
+
510
+ #[ cfg( windows) ]
511
+ return Ok ( if this. tcx . sess . target . target . target_os == "windows" {
512
+ // Windows-on-Windows, all fine.
513
+ Cow :: Borrowed ( Path :: new ( os_str) )
514
+ } else {
515
+ // Unix target, Windows host. Need to convert target '/' to host '\'.
516
+ let converted = os_str
517
+ . encode_wide ( )
518
+ . map ( |wchar| if wchar == '/' as u16 { '\\' as u16 } else { wchar } )
519
+ . collect :: < Vec < _ > > ( ) ;
520
+ Cow :: Owned ( PathBuf :: from ( OsString :: from_wide ( & converted) ) )
521
+ } ) ;
522
+ #[ cfg( unix) ]
523
+ return Ok ( if this. tcx . sess . target . target . target_os == "windows" {
524
+ // Windows target, Unix host. Need to convert target '\' to host '/'.
525
+ let converted = os_str
526
+ . as_bytes ( )
527
+ . iter ( )
528
+ . map ( |& wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar } )
529
+ . collect :: < Vec < _ > > ( ) ;
530
+ Cow :: Owned ( PathBuf :: from ( OsString :: from_vec ( converted) ) )
531
+ } else {
532
+ // Unix-on-Unix, all is fine.
533
+ Cow :: Borrowed ( Path :: new ( os_str) )
534
+ } ) ;
504
535
}
505
536
506
537
/// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
@@ -512,7 +543,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
512
543
{
513
544
#[ cfg( windows) ]
514
545
pub fn u16vec_to_osstring < ' tcx , ' a > ( u16_vec : Vec < u16 > ) -> InterpResult < ' tcx , OsString > {
515
- Ok ( std :: os :: windows :: ffi :: OsStringExt :: from_wide ( & u16_vec[ ..] ) )
546
+ Ok ( OsString :: from_wide ( & u16_vec[ ..] ) )
516
547
}
517
548
#[ cfg( not( windows) ) ]
518
549
pub fn u16vec_to_osstring < ' tcx , ' a > ( u16_vec : Vec < u16 > ) -> InterpResult < ' tcx , OsString > {
@@ -538,7 +569,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
538
569
) -> InterpResult < ' tcx , ( bool , u64 ) > {
539
570
#[ cfg( unix) ]
540
571
fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
541
- Ok ( std :: os :: unix :: ffi :: OsStrExt :: as_bytes ( os_str ) )
572
+ Ok ( os_str . as_bytes ( ) )
542
573
}
543
574
#[ cfg( not( unix) ) ]
544
575
fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
@@ -571,8 +602,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
571
602
scalar : Scalar < Tag > ,
572
603
size : u64 ,
573
604
) -> InterpResult < ' tcx , ( bool , u64 ) > {
574
- let os_str = path. as_os_str ( ) ;
575
- self . write_os_str_to_c_str ( os_str, scalar, size)
605
+ let this = self . eval_context_mut ( ) ;
606
+
607
+ #[ cfg( windows) ]
608
+ let os_str = if this. tcx . sess . target . target . target_os == "windows" {
609
+ // Windows-on-Windows, all fine.
610
+ Cow :: Borrowed ( path. as_os_str ( ) )
611
+ } else {
612
+ // Unix target, Windows host. Need to convert host '\\' to target '/'.
613
+ let converted = path
614
+ . as_os_str ( )
615
+ . encode_wide ( )
616
+ . map ( |wchar| if wchar == '\\' as u16 { '/' as u16 } else { wchar } )
617
+ . collect :: < Vec < _ > > ( ) ;
618
+ Cow :: Owned ( OsString :: from_wide ( & converted) )
619
+ } ;
620
+ #[ cfg( unix) ]
621
+ let os_str = if this. tcx . sess . target . target . target_os == "windows" {
622
+ // Windows target, Unix host. Need to convert host '/' to target '\'.
623
+ let converted = path
624
+ . as_os_str ( )
625
+ . as_bytes ( )
626
+ . iter ( )
627
+ . map ( |& wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar } )
628
+ . collect :: < Vec < _ > > ( ) ;
629
+ Cow :: Owned ( OsString :: from_vec ( converted) )
630
+ } else {
631
+ // Unix-on-Unix, all is fine.
632
+ Cow :: Borrowed ( path. as_os_str ( ) )
633
+ } ;
634
+
635
+ this. write_os_str_to_c_str ( & os_str, scalar, size)
576
636
}
577
637
578
638
/// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what
@@ -588,7 +648,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
588
648
) -> InterpResult < ' tcx , ( bool , u64 ) > {
589
649
#[ cfg( windows) ]
590
650
fn os_str_to_u16vec < ' tcx > ( os_str : & OsStr ) -> InterpResult < ' tcx , Vec < u16 > > {
591
- Ok ( std :: os :: windows :: ffi :: OsStrExt :: encode_wide ( os_str ) . collect ( ) )
651
+ Ok ( os_str . encode_wide ( ) . collect ( ) )
592
652
}
593
653
#[ cfg( not( windows) ) ]
594
654
fn os_str_to_u16vec < ' tcx > ( os_str : & OsStr ) -> InterpResult < ' tcx , Vec < u16 > > {
0 commit comments