Auto merge of #1436 - samrat:support-stdin-read, r=RalfJung
Handle `read`s on STDIN Closes #1434
This commit is contained in:
commit
b021209b0e
@ -1,4 +1,5 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use log::trace;
|
||||
|
||||
@ -67,7 +68,37 @@ fn emulate_foreign_item_by_name(
|
||||
let buf = this.read_scalar(buf)?.not_undef()?;
|
||||
let count = this.read_scalar(count)?.to_machine_usize(this)?;
|
||||
let result = if fd == 0 {
|
||||
throw_unsup_format!("reading from stdin is not implemented")
|
||||
|
||||
this.check_no_isolation("read")?;
|
||||
|
||||
// We cap the number of read bytes to the largest
|
||||
// value that we are able to fit in both the
|
||||
// host's and target's `isize`. This saves us from
|
||||
// having to handle overflows later.
|
||||
let count = count.min(this.machine_isize_max() as u64).min(isize::MAX as u64);
|
||||
|
||||
// We want to read at most `count` bytes. We are
|
||||
// sure that `count` is not negative because it
|
||||
// was a target's `usize`. Also we are sure that
|
||||
// its smaller than `usize::MAX` because it is a
|
||||
// host's `isize`.
|
||||
let mut buffer = vec![0; count as usize];
|
||||
let res = io::stdin()
|
||||
.read(&mut buffer)
|
||||
// `Stdin::read` never returns a value larger
|
||||
// than `count`, so this cannot fail.
|
||||
.map(|c| i64::try_from(c).unwrap());
|
||||
|
||||
match res {
|
||||
Ok(bytes) => {
|
||||
this.memory.write_bytes(buf, buffer)?;
|
||||
i64::try_from(bytes).unwrap()
|
||||
},
|
||||
Err(e) => {
|
||||
this.set_last_error_from_io_error(e)?;
|
||||
-1
|
||||
},
|
||||
}
|
||||
} else if fd == 1 || fd == 2 {
|
||||
throw_unsup_format!("cannot read from stdout/stderr")
|
||||
} else {
|
||||
@ -85,7 +116,6 @@ fn emulate_foreign_item_by_name(
|
||||
throw_unsup_format!("cannot write to stdin")
|
||||
} else if fd == 1 || fd == 2 {
|
||||
// stdout/stderr
|
||||
use std::io::{self, Write};
|
||||
|
||||
let buf_cont = this.memory.read_bytes(buf, Size::from_bytes(count))?;
|
||||
// We need to flush to make sure this actually appears on the screen
|
||||
@ -103,6 +133,7 @@ fn emulate_foreign_item_by_name(
|
||||
};
|
||||
match res {
|
||||
Ok(n) => i64::try_from(n).unwrap(),
|
||||
// FIXME: set errno to appropriate value
|
||||
Err(_) => -1,
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user