@@ -14,72 +14,48 @@ use rustc_target::abi::LayoutOf;
14
14
use crate :: * ;
15
15
16
16
/// Represent how path separator conversion should be done.
17
- enum Pathconversion {
17
+ pub enum PathConversion {
18
18
HostToTarget ,
19
19
TargetToHost ,
20
20
}
21
21
22
- /// Perform path separator conversion if needed.
23
- fn convert_path_separator < ' a > (
24
- os_str : Cow < ' a , OsStr > ,
25
- target_os : & str ,
26
- direction : Pathconversion ,
27
- ) -> Cow < ' a , OsStr > {
28
- #[ cfg( windows) ]
29
- return if target_os == "windows" {
30
- // Windows-on-Windows, all fine.
31
- os_str
32
- } else {
33
- // Unix target, Windows host.
34
- let ( from, to) = match direction {
35
- Pathconversion :: HostToTarget => ( '\\' , '/' ) ,
36
- Pathconversion :: TargetToHost => ( '/' , '\\' ) ,
37
- } ;
38
- let converted = os_str
39
- . encode_wide ( )
40
- . map ( |wchar| if wchar == from as u16 { to as u16 } else { wchar } )
41
- . collect :: < Vec < _ > > ( ) ;
42
- Cow :: Owned ( OsString :: from_wide ( & converted) )
43
- } ;
44
- #[ cfg( unix) ]
45
- return if target_os == "windows" {
46
- // Windows target, Unix host.
47
- let ( from, to) = match direction {
48
- Pathconversion :: HostToTarget => ( '/' , '\\' ) ,
49
- Pathconversion :: TargetToHost => ( '\\' , '/' ) ,
50
- } ;
51
- let converted = os_str
52
- . as_bytes ( )
53
- . iter ( )
54
- . map ( |& wchar| if wchar == from as u8 { to as u8 } else { wchar } )
55
- . collect :: < Vec < _ > > ( ) ;
56
- Cow :: Owned ( OsString :: from_vec ( converted) )
57
- } else {
58
- // Unix-on-Unix, all is fine.
59
- os_str
60
- } ;
22
+ #[ cfg( unix) ]
23
+ pub fn os_str_to_bytes < ' a , ' tcx > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
24
+ Ok ( os_str. as_bytes ( ) )
25
+ }
26
+
27
+ #[ cfg( not( unix) ) ]
28
+ pub fn os_str_to_bytes < ' a , ' tcx > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
29
+ // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
30
+ // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
31
+ // valid.
32
+ os_str
33
+ . to_str ( )
34
+ . map ( |s| s. as_bytes ( ) )
35
+ . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
36
+ }
37
+
38
+ #[ cfg( unix) ]
39
+ pub fn bytes_to_os_str < ' a , ' tcx > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
40
+ Ok ( OsStr :: from_bytes ( bytes) )
41
+ }
42
+ #[ cfg( not( unix) ) ]
43
+ pub fn bytes_to_os_str < ' a , ' tcx > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
44
+ let s = std:: str:: from_utf8 ( bytes)
45
+ . map_err ( |_| err_unsup_format ! ( "{:?} is not a valid utf-8 string" , bytes) ) ?;
46
+ Ok ( OsStr :: new ( s) )
61
47
}
62
48
63
49
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
64
50
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
51
+
65
52
/// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
66
53
/// the Unix APIs usually handle.
67
54
fn read_os_str_from_c_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , & ' a OsStr >
68
55
where
69
56
' tcx : ' a ,
70
57
' mir : ' a ,
71
58
{
72
- #[ cfg( unix) ]
73
- fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
74
- Ok ( OsStr :: from_bytes ( bytes) )
75
- }
76
- #[ cfg( not( unix) ) ]
77
- fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
78
- let s = std:: str:: from_utf8 ( bytes)
79
- . map_err ( |_| err_unsup_format ! ( "{:?} is not a valid utf-8 string" , bytes) ) ?;
80
- Ok ( OsStr :: new ( s) )
81
- }
82
-
83
59
let this = self . eval_context_ref ( ) ;
84
60
let bytes = this. memory . read_c_str ( scalar) ?;
85
61
bytes_to_os_str ( bytes)
@@ -118,20 +94,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
118
94
scalar : Scalar < Tag > ,
119
95
size : u64 ,
120
96
) -> InterpResult < ' tcx , ( bool , u64 ) > {
121
- #[ cfg( unix) ]
122
- fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
123
- Ok ( os_str. as_bytes ( ) )
124
- }
125
- #[ cfg( not( unix) ) ]
126
- fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
127
- // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
128
- // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
129
- // valid.
130
- os_str
131
- . to_str ( )
132
- . map ( |s| s. as_bytes ( ) )
133
- . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
134
- }
135
97
136
98
let bytes = os_str_to_bytes ( os_str) ?;
137
99
// If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
@@ -226,7 +188,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
226
188
let this = self . eval_context_ref ( ) ;
227
189
let os_str = this. read_os_str_from_c_str ( scalar) ?;
228
190
229
- Ok ( match convert_path_separator ( Cow :: Borrowed ( os_str) , & this . tcx . sess . target . target . target_os , Pathconversion :: TargetToHost ) {
191
+ Ok ( match this . convert_path_separator ( Cow :: Borrowed ( os_str) , PathConversion :: TargetToHost ) {
230
192
Cow :: Borrowed ( x) => Cow :: Borrowed ( Path :: new ( x) ) ,
231
193
Cow :: Owned ( y) => Cow :: Owned ( PathBuf :: from ( y) ) ,
232
194
} )
@@ -237,7 +199,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
237
199
let this = self . eval_context_ref ( ) ;
238
200
let os_str = this. read_os_str_from_wide_str ( scalar) ?;
239
201
240
- Ok ( convert_path_separator ( Cow :: Owned ( os_str) , & this . tcx . sess . target . target . target_os , Pathconversion :: TargetToHost ) . into_owned ( ) . into ( ) )
202
+ Ok ( this . convert_path_separator ( Cow :: Owned ( os_str) , PathConversion :: TargetToHost ) . into_owned ( ) . into ( ) )
241
203
}
242
204
243
205
/// Write a Path to the machine memory (as a null-terminated sequence of bytes),
@@ -249,7 +211,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
249
211
size : u64 ,
250
212
) -> InterpResult < ' tcx , ( bool , u64 ) > {
251
213
let this = self . eval_context_mut ( ) ;
252
- let os_str = convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , & this . tcx . sess . target . target . target_os , Pathconversion :: HostToTarget ) ;
214
+ let os_str = this . convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , PathConversion :: HostToTarget ) ;
253
215
this. write_os_str_to_c_str ( & os_str, scalar, size)
254
216
}
255
217
@@ -262,7 +224,50 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
262
224
size : u64 ,
263
225
) -> InterpResult < ' tcx , ( bool , u64 ) > {
264
226
let this = self . eval_context_mut ( ) ;
265
- let os_str = convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , & this . tcx . sess . target . target . target_os , Pathconversion :: HostToTarget ) ;
227
+ let os_str = this . convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , PathConversion :: HostToTarget ) ;
266
228
this. write_os_str_to_wide_str ( & os_str, scalar, size)
267
229
}
230
+
231
+ fn convert_path_separator < ' a > (
232
+ & self ,
233
+ os_str : Cow < ' a , OsStr > ,
234
+ direction : PathConversion ,
235
+ ) -> Cow < ' a , OsStr > {
236
+ let this = self . eval_context_ref ( ) ;
237
+ let target_os = & this. tcx . sess . target . target . target_os ;
238
+ #[ cfg( windows) ]
239
+ return if target_os == "windows" {
240
+ // Windows-on-Windows, all fine.
241
+ os_str
242
+ } else {
243
+ // Unix target, Windows host.
244
+ let ( from, to) = match direction {
245
+ PathConversion :: HostToTarget => ( '\\' , '/' ) ,
246
+ PathConversion :: TargetToHost => ( '/' , '\\' ) ,
247
+ } ;
248
+ let converted = os_str
249
+ . encode_wide ( )
250
+ . map ( |wchar| if wchar == from as u16 { to as u16 } else { wchar } )
251
+ . collect :: < Vec < _ > > ( ) ;
252
+ Cow :: Owned ( OsString :: from_wide ( & converted) )
253
+ } ;
254
+ #[ cfg( unix) ]
255
+ return if target_os == "windows" {
256
+ // Windows target, Unix host.
257
+ let ( from, to) = match direction {
258
+ PathConversion :: HostToTarget => ( '/' , '\\' ) ,
259
+ PathConversion :: TargetToHost => ( '\\' , '/' ) ,
260
+ } ;
261
+ let converted = os_str
262
+ . as_bytes ( )
263
+ . iter ( )
264
+ . map ( |& wchar| if wchar == from as u8 { to as u8 } else { wchar } )
265
+ . collect :: < Vec < _ > > ( ) ;
266
+ Cow :: Owned ( OsString :: from_vec ( converted) )
267
+ } else {
268
+ // Unix-on-Unix, all is fine.
269
+ os_str
270
+ } ;
271
+ }
268
272
}
273
+
0 commit comments