|  | @@ -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<u8>,
 | 
	
		
			
				|  |  | +    unget: Vec<u8>,
 | 
	
		
			
				|  |  |      // pub for stdio_ext
 | 
	
		
			
				|  |  |      pub(crate) writer: LineWriter<File>,
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -86,11 +87,12 @@ pub struct FILE {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  impl Read for FILE {
 | 
	
		
			
				|  |  |      fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
 | 
	
		
			
				|  |  | -        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
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |