diff --git a/src/header/stdio/default.rs b/src/header/stdio/default.rs index 592a77845b..b86115e2d6 100644 --- a/src/header/stdio/default.rs +++ b/src/header/stdio/default.rs @@ -2,6 +2,7 @@ use super::{constants, Buffer, BUFSIZ, FILE}; use core::{cell::UnsafeCell, ptr}; use crate::{fs::File, io::LineWriter, platform::types::*, sync::Mutex}; +use alloc::vec::Vec; pub struct GlobalFile(UnsafeCell); impl GlobalFile { @@ -16,7 +17,7 @@ impl GlobalFile { read_buf: Buffer::Owned(vec![0; BUFSIZ as usize]), read_pos: 0, read_size: 0, - unget: None, + unget: Vec::new(), writer, pid: None, diff --git a/src/header/stdio/helpers.rs b/src/header/stdio/helpers.rs index 399a8a8991..6d5d9da841 100644 --- a/src/header/stdio/helpers.rs +++ b/src/header/stdio/helpers.rs @@ -1,5 +1,6 @@ use alloc::boxed::Box; +use super::{constants::*, Buffer, FILE}; use crate::{ fs::File, header::{errno, fcntl::*, string::strchr}, @@ -7,8 +8,7 @@ use crate::{ platform::{self, types::*}, sync::Mutex, }; - -use super::{constants::*, Buffer, FILE}; +use alloc::vec::Vec; /// Parse mode flags as a string and output a mode flags integer pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 { @@ -72,7 +72,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> { read_buf: Buffer::Owned(vec![0; BUFSIZ as usize]), read_pos: 0, read_size: 0, - unget: None, + unget: Vec::new(), writer, pid: None, diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index 0163ea1c86..636c6a1ae5 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -6,6 +6,7 @@ use alloc::{ vec::Vec, }; use core::{ + cmp, ffi::VaList as va_list, fmt::{self, Write as WriteFmt}, mem, @@ -76,7 +77,7 @@ pub struct FILE { read_buf: Buffer<'static>, read_pos: usize, read_size: usize, - unget: Option, + unget: Vec, // pub for stdio_ext pub(crate) writer: LineWriter, @@ -86,11 +87,12 @@ pub struct FILE { impl Read for FILE { fn read(&mut self, out: &mut [u8]) -> io::Result { - if !out.is_empty() { - if let Some(c) = self.unget.take() { - out[0] = c; - return Ok(1); - } + let unget_read_size = cmp::min(out.len(), self.unget.len()); + for i in 0..unget_read_size { + out[i] = self.unget.pop().unwrap(); + } + if unget_read_size != 0 { + return Ok(unget_read_size); } let len = { @@ -311,11 +313,12 @@ pub unsafe extern "C" fn fgets( let mut wrote = false; if left >= 1 { - if let Some(c) = stream.unget.take() { - *out = c as c_char; + let unget_read_size = cmp::min(left, stream.unget.len()); + for _ in 0..unget_read_size { + *out = stream.unget.pop().unwrap() as i8; out = out.offset(1); - left -= 1; } + left -= unget_read_size; } loop { @@ -533,7 +536,7 @@ pub unsafe extern "C" fn fseeko(stream: *mut FILE, mut off: off_t, whence: c_int stream.flags &= !(F_EOF | F_ERR); stream.read_pos = 0; stream.read_size = 0; - stream.unget = None; + stream.unget = Vec::new(); 0 } @@ -990,11 +993,7 @@ unsafe extern "C" fn tmpnam_inner(buf: *mut c_char, offset: usize) -> *mut c_cha #[no_mangle] pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int { let mut stream = (*stream).lock(); - if stream.unget.is_some() { - platform::errno = errno::EIO; - return EOF; - } - stream.unget = Some(c as u8); + stream.unget.push(c as u8); c }