Skip to content

Commit eaf5d32

Browse files
committed
Auto merge of #1501 - samrat:fix-fs-error-handling, r=RalfJung
Bubble up errors from FileDescriptor::as_file_handle Instead of indicating incorrectly that a handle was not found, return the error from `as_file_handle` indicating the operation is not supported on the FD. Addresses some comments in #1495
2 parents 302ccf4 + 1069f6b commit eaf5d32

File tree

1 file changed

+55
-75
lines changed

1 file changed

+55
-75
lines changed

src/shims/posix/fs.rs

Lines changed: 55 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -484,9 +484,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
484484
}
485485
let fh = &mut this.machine.file_handler;
486486
let (file_result, writable) = match fh.handles.get(&fd) {
487-
Some(file_descriptor) => match file_descriptor.as_file_handle() {
488-
Ok(FileHandle { file, writable }) => (file.try_clone(), *writable),
489-
Err(_) => return this.handle_not_found(),
487+
Some(file_descriptor) => {
488+
// FIXME: Support "dup" for all FDs(stdin, etc)
489+
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
490+
(file.try_clone(), *writable)
490491
},
491492
None => return this.handle_not_found(),
492493
};
@@ -499,13 +500,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
499500
{
500501
let &[_, _] = check_arg_count(args)?;
501502
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
502-
match file_descriptor.as_file_handle() {
503-
Ok(FileHandle { file, writable }) => {
504-
let io_result = maybe_sync_file(&file, *writable, File::sync_all);
505-
this.try_unwrap_io_result(io_result)
506-
},
507-
Err(_) => this.handle_not_found(),
508-
}
503+
// FIXME: Support fullfsync for all FDs
504+
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
505+
let io_result = maybe_sync_file(&file, *writable, File::sync_all);
506+
this.try_unwrap_io_result(io_result)
509507
} else {
510508
this.handle_not_found()
511509
}
@@ -522,28 +520,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
522520
let fd = this.read_scalar(fd_op)?.to_i32()?;
523521

524522
if let Some(file_descriptor) = this.machine.file_handler.handles.remove(&fd) {
525-
match file_descriptor.as_file_handle() {
526-
Ok(FileHandle { file, writable }) => {
527-
// We sync the file if it was opened in a mode different than read-only.
528-
if *writable {
529-
// `File::sync_all` does the checks that are done when closing a file. We do this to
530-
// to handle possible errors correctly.
531-
let result = this.try_unwrap_io_result(file.sync_all().map(|_| 0i32));
532-
// Now we actually close the file.
533-
drop(file);
534-
// And return the result.
535-
result
536-
} else {
537-
// We drop the file, this closes it but ignores any errors produced when closing
538-
// it. This is done because `File::sync_all` cannot be done over files like
539-
// `/dev/urandom` which are read-only. Check
540-
// https://github.com/rust-lang/miri/issues/999#issuecomment-568920439 for a deeper
541-
// discussion.
542-
drop(file);
543-
Ok(0)
544-
}
545-
},
546-
Err(_) => this.handle_not_found()
523+
// FIXME: Support `close` for all FDs(stdin, etc)
524+
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
525+
// We sync the file if it was opened in a mode different than read-only.
526+
if *writable {
527+
// `File::sync_all` does the checks that are done when closing a file. We do this to
528+
// to handle possible errors correctly.
529+
let result = this.try_unwrap_io_result(file.sync_all().map(|_| 0i32));
530+
// Now we actually close the file.
531+
drop(file);
532+
// And return the result.
533+
result
534+
} else {
535+
// We drop the file, this closes it but ignores any errors produced when closing
536+
// it. This is done because `File::sync_all` cannot be done over files like
537+
// `/dev/urandom` which are read-only. Check
538+
// https://github.com/rust-lang/miri/issues/999#issuecomment-568920439 for a deeper
539+
// discussion.
540+
drop(file);
541+
Ok(0)
547542
}
548543
} else {
549544
this.handle_not_found()
@@ -1223,25 +1218,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
12231218
let fd = this.read_scalar(fd_op)?.to_i32()?;
12241219
let length = this.read_scalar(length_op)?.to_i64()?;
12251220
if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) {
1226-
match file_descriptor.as_file_handle() {
1227-
Ok(FileHandle { file, writable }) => {
1228-
if *writable {
1229-
if let Ok(length) = length.try_into() {
1230-
let result = file.set_len(length);
1231-
this.try_unwrap_io_result(result.map(|_| 0i32))
1232-
} else {
1233-
let einval = this.eval_libc("EINVAL")?;
1234-
this.set_last_error(einval)?;
1235-
Ok(-1)
1236-
}
1237-
} else {
1238-
// The file is not writable
1239-
let einval = this.eval_libc("EINVAL")?;
1240-
this.set_last_error(einval)?;
1241-
Ok(-1)
1242-
}
1221+
// FIXME: Support ftruncate64 for all FDs
1222+
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
1223+
if *writable {
1224+
if let Ok(length) = length.try_into() {
1225+
let result = file.set_len(length);
1226+
this.try_unwrap_io_result(result.map(|_| 0i32))
1227+
} else {
1228+
let einval = this.eval_libc("EINVAL")?;
1229+
this.set_last_error(einval)?;
1230+
Ok(-1)
12431231
}
1244-
Err(_) => this.handle_not_found()
1232+
} else {
1233+
// The file is not writable
1234+
let einval = this.eval_libc("EINVAL")?;
1235+
this.set_last_error(einval)?;
1236+
Ok(-1)
12451237
}
12461238
} else {
12471239
this.handle_not_found()
@@ -1260,13 +1252,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
12601252

12611253
let fd = this.read_scalar(fd_op)?.to_i32()?;
12621254
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
1263-
match file_descriptor.as_file_handle() {
1264-
Ok(FileHandle { file, writable }) => {
1265-
let io_result = maybe_sync_file(&file, *writable, File::sync_all);
1266-
this.try_unwrap_io_result(io_result)
1267-
}
1268-
Err(_) => this.handle_not_found()
1269-
}
1255+
// FIXME: Support fsync for all FDs
1256+
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
1257+
let io_result = maybe_sync_file(&file, *writable, File::sync_all);
1258+
this.try_unwrap_io_result(io_result)
12701259
} else {
12711260
this.handle_not_found()
12721261
}
@@ -1279,13 +1268,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
12791268

12801269
let fd = this.read_scalar(fd_op)?.to_i32()?;
12811270
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
1282-
match file_descriptor.as_file_handle() {
1283-
Ok(FileHandle { file, writable }) => {
1284-
let io_result = maybe_sync_file(&file, *writable, File::sync_data);
1285-
this.try_unwrap_io_result(io_result)
1286-
}
1287-
Err(_) => this.handle_not_found()
1288-
}
1271+
// FIXME: Support fdatasync for all FDs
1272+
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
1273+
let io_result = maybe_sync_file(&file, *writable, File::sync_data);
1274+
this.try_unwrap_io_result(io_result)
12891275
} else {
12901276
this.handle_not_found()
12911277
}
@@ -1322,13 +1308,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
13221308
}
13231309

13241310
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
1325-
match file_descriptor.as_file_handle() {
1326-
Ok(FileHandle { file, writable }) => {
1327-
let io_result = maybe_sync_file(&file, *writable, File::sync_data);
1328-
this.try_unwrap_io_result(io_result)
1329-
},
1330-
Err(_) => this.handle_not_found()
1331-
}
1311+
// FIXME: Support sync_data_range for all FDs
1312+
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
1313+
let io_result = maybe_sync_file(&file, *writable, File::sync_data);
1314+
this.try_unwrap_io_result(io_result)
13321315
} else {
13331316
this.handle_not_found()
13341317
}
@@ -1378,10 +1361,7 @@ impl FileMetadata {
13781361
) -> InterpResult<'tcx, Option<FileMetadata>> {
13791362
let option = ecx.machine.file_handler.handles.get(&fd);
13801363
let file = match option {
1381-
Some(file_descriptor) => match file_descriptor.as_file_handle() {
1382-
Ok(FileHandle { file, writable: _ }) => file,
1383-
Err(_) => return ecx.handle_not_found().map(|_: i32| None),
1384-
},
1364+
Some(file_descriptor) => &file_descriptor.as_file_handle()?.file,
13851365
None => return ecx.handle_not_found().map(|_: i32| None),
13861366
};
13871367
let metadata = file.metadata();

0 commit comments

Comments
 (0)