@@ -15,6 +15,7 @@ use shims::time::system_time_to_duration;
15
15
#[ derive( Debug ) ]
16
16
pub struct FileHandle {
17
17
file : File ,
18
+ writable : bool ,
18
19
}
19
20
20
21
pub struct FileHandler {
@@ -56,10 +57,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
56
57
if ( o_rdonly | o_wronly | o_rdwr) & !0b11 != 0 {
57
58
throw_unsup_format ! ( "Access mode flags on this platform are unsupported" ) ;
58
59
}
60
+ let mut writable = true ;
61
+
59
62
// Now we check the access mode
60
63
let access_mode = flag & 0b11 ;
61
64
62
65
if access_mode == o_rdonly {
66
+ writable = false ;
63
67
options. read ( true ) ;
64
68
} else if access_mode == o_wronly {
65
69
options. write ( true ) ;
@@ -105,7 +109,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
105
109
let fd = options. open ( & path) . map ( |file| {
106
110
let mut fh = & mut this. machine . file_handler ;
107
111
fh. low += 1 ;
108
- fh. handles . insert ( fh. low , FileHandle { file } ) . unwrap_none ( ) ;
112
+ fh. handles . insert ( fh. low , FileHandle { file, writable } ) . unwrap_none ( ) ;
109
113
fh. low
110
114
} ) ;
111
115
@@ -148,13 +152,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
148
152
let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
149
153
150
154
if let Some ( handle) = this. machine . file_handler . handles . remove ( & fd) {
151
- // `File::sync_all` does the checks that are done when closing a file. We do this to
152
- // to handle possible errors correctly.
153
- let result = this. try_unwrap_io_result ( handle. file . sync_all ( ) . map ( |_| 0i32 ) ) ;
154
- // Now we actually close the file.
155
- drop ( handle) ;
156
- // And return the result.
157
- result
155
+ // We sync the file if it was opened in a mode different than read-only.
156
+ if handle. writable {
157
+ // `File::sync_all` does the checks that are done when closing a file. We do this to
158
+ // to handle possible errors correctly.
159
+ let result = this. try_unwrap_io_result ( handle. file . sync_all ( ) . map ( |_| 0i32 ) ) ;
160
+ // Now we actually close the file.
161
+ drop ( handle) ;
162
+ // And return the result.
163
+ result
164
+ } else {
165
+ // We drop the file, this closes it but ignores any errors produced when closing
166
+ // it. This is done because `File::sync_call` cannot be done over files like
167
+ // `/dev/urandom` which are read-only. Check
168
+ // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439 for a deeper
169
+ // discussion.
170
+ drop ( handle) ;
171
+ Ok ( 0 )
172
+ }
158
173
} else {
159
174
this. handle_not_found ( )
160
175
}
0 commit comments