Skip to content

Commit 894e7bd

Browse files
committed
Attempt to improve the OpenOptions handling a bit
1 parent 6494b1f commit 894e7bd

File tree

2 files changed

+38
-34
lines changed

2 files changed

+38
-34
lines changed

src/shims/windows/fs.rs

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -233,40 +233,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
233233
);
234234
}
235235

236-
match creation_disposition {
237-
CreateAlways | OpenAlways => {
238-
// Per the documentation:
239-
// If the specified file exists and is writable, the function truncates the file,
240-
// the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS.
241-
// If the specified file does not exist and is a valid path, a new file is created,
242-
// the function succeeds, and the last-error code is set to zero.
243-
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
244-
//
245-
// This is racy, but there doesn't appear to be an std API that both succeeds if a
246-
// file exists but tells us it isn't new. Either we accept racing one way or another,
247-
// or we use an iffy heuristic like file creation time. This implementation prefers
248-
// to fail in the direction of erroring more often.
249-
if file_name.exists() {
250-
this.set_last_error(IoError::WindowsError("ERROR_ALREADY_EXISTS"))?;
251-
}
252-
options.create(true);
253-
if creation_disposition == CreateAlways {
254-
options.truncate(true);
255-
}
256-
}
257-
CreateNew => {
258-
options.create_new(true);
259-
// Per `create_new` documentation:
260-
// The file must be opened with write or append access in order to create a new file.
261-
// https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create_new
262-
if !desired_write {
263-
options.append(true);
264-
}
265-
}
266-
OpenExisting => {} // Default options
267-
TruncateExisting => {
268-
options.truncate(true);
269-
}
236+
// Per the documentation:
237+
// If the specified file exists and is writable, the function truncates the file,
238+
// the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS.
239+
// If the specified file does not exist and is a valid path, a new file is created,
240+
// the function succeeds, and the last-error code is set to zero.
241+
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
242+
//
243+
// This is racy, but there doesn't appear to be an std API that both succeeds if a
244+
// file exists but tells us it isn't new. Either we accept racing one way or another,
245+
// or we use an iffy heuristic like file creation time. This implementation prefers
246+
// to fail in the direction of erroring more often.
247+
if let CreateAlways | OpenAlways = creation_disposition
248+
&& file_name.exists()
249+
{
250+
this.set_last_error(IoError::WindowsError("ERROR_ALREADY_EXISTS"))?;
270251
}
271252

272253
let handle = if is_dir {
@@ -282,6 +263,28 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
282263
Handle::File(fd_num)
283264
})
284265
} else {
266+
match creation_disposition {
267+
CreateAlways | OpenAlways => {
268+
options.create(true);
269+
if creation_disposition == CreateAlways {
270+
options.truncate(true);
271+
}
272+
}
273+
CreateNew => {
274+
options.create_new(true);
275+
// Per `create_new` documentation:
276+
// The file must be opened with write or append access in order to create a new file.
277+
// https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create_new
278+
if !desired_write {
279+
options.append(true);
280+
}
281+
}
282+
OpenExisting => {} // Default options
283+
TruncateExisting => {
284+
options.truncate(true);
285+
}
286+
}
287+
285288
options.open(file_name).map(|file| {
286289
let fh = &mut this.machine.fds;
287290
let fd_num = fh.insert_new(FileHandle { file, writable: desired_write });

tests/pass-dep/shims/windows-fs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ fn main() {
2525
test_create_normal_file();
2626
test_create_always_twice();
2727
test_open_always_twice();
28+
test_open_dir_reparse();
2829
}
2930
}
3031

0 commit comments

Comments
 (0)