Don't forget to lock stdout when printfing

This commit is contained in:
jD91mZM2
2018-08-08 13:25:26 +02:00
parent 23a8855e50
commit b26213731c
3 changed files with 57 additions and 37 deletions
+18 -16
View File
@@ -129,12 +129,12 @@ impl<'a, W: Write> Write for &'a mut W {
}
pub trait Read {
fn read_u8(&mut self, byte: &mut u8) -> bool;
fn read_u8(&mut self) -> Result<Option<u8>, ()>;
}
impl<'a, R: Read> Read for &'a mut R {
fn read_u8(&mut self, byte: &mut u8) -> bool {
(**self).read_u8(byte)
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
(**self).read_u8()
}
}
@@ -169,11 +169,13 @@ impl FileReader {
}
impl Read for FileReader {
fn read_u8(&mut self, byte: &mut u8) -> bool {
let mut buf = [*byte];
let n = self.read(&mut buf);
*byte = buf[0];
n > 0
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
let mut buf = [0];
match self.read(&mut buf) {
0 => Ok(None),
n if n < 0 => Err(()),
_ => Ok(Some(buf[0]))
}
}
}
@@ -241,13 +243,13 @@ impl Write for UnsafeStringWriter {
pub struct StringReader<'a>(pub &'a [u8]);
impl<'a> Read for StringReader<'a> {
fn read_u8(&mut self, byte: &mut u8) -> bool {
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
if self.0.is_empty() {
false
Ok(None)
} else {
*byte = self.0[0];
let byte = self.0[0];
self.0 = &self.0[1..];
true
Ok(Some(byte))
}
}
}
@@ -255,14 +257,14 @@ impl<'a> Read for StringReader<'a> {
pub struct UnsafeStringReader(pub *const u8);
impl Read for UnsafeStringReader {
fn read_u8(&mut self, byte: &mut u8) -> bool {
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
unsafe {
if *self.0 == 0 {
false
Ok(None)
} else {
*byte = *self.0;
let byte = *self.0;
self.0 = self.0.offset(1);
true
Ok(Some(byte))
}
}
}
+31 -17
View File
@@ -16,7 +16,7 @@ extern crate string;
extern crate va_list as vl;
use core::fmt::Write as WriteFmt;
use core::fmt::{self, Error, Result};
use core::fmt::{self, Error};
use core::sync::atomic::{AtomicBool, Ordering};
use core::{ptr, str};
@@ -171,38 +171,52 @@ impl FILE {
pub fn seek(&self, off: off_t, whence: c_int) -> off_t {
platform::lseek(self.fd, off, whence)
}
pub fn lock(&mut self) -> LockGuard {
flockfile(self);
LockGuard(self)
}
}
impl fmt::Write for FILE {
fn write_str(&mut self, s: &str) -> Result {
if !self.can_write() {
pub struct LockGuard<'a>(&'a mut FILE);
impl<'a> Drop for LockGuard<'a> {
fn drop(&mut self) {
funlockfile(self.0);
}
}
impl<'a> fmt::Write for LockGuard<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
if !self.0.can_write() {
return Err(Error);
}
let s = s.as_bytes();
if self.write(s) != s.len() {
if self.0.write(s) != s.len() {
Err(Error)
} else {
Ok(())
}
}
}
impl Write for FILE {
fn write_u8(&mut self, byte: u8) -> Result {
if !self.can_write() {
impl<'a> Write for LockGuard<'a> {
fn write_u8(&mut self, byte: u8) -> fmt::Result {
if !self.0.can_write() {
return Err(Error);
}
if self.write(&[byte]) != 1 {
if self.0.write(&[byte]) != 1 {
Err(Error)
} else {
Ok(())
}
}
}
impl Read for FILE {
fn read_u8(&mut self, byte: &mut u8) -> bool {
let mut buf = [*byte];
let n = self.read(&mut buf);
*byte = buf[0];
n > 0
impl<'a> Read for LockGuard<'a> {
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
let mut buf = [0];
match self.0.read(&mut buf) {
0 => Ok(None),
_ => Ok(Some(buf[0]))
}
}
}
@@ -913,7 +927,7 @@ pub extern "C" fn ungetc(c: c_int, stream: &mut FILE) -> c_int {
#[no_mangle]
pub unsafe extern "C" fn vfprintf(file: &mut FILE, format: *const c_char, ap: va_list) -> c_int {
printf::printf(file, format, ap)
printf::printf(file.lock(), format, ap)
}
#[no_mangle]
@@ -942,7 +956,7 @@ pub unsafe extern "C" fn vsprintf(s: *mut c_char, format: *const c_char, ap: va_
#[no_mangle]
pub unsafe extern "C" fn vfscanf(file: &mut FILE, format: *const c_char, ap: va_list) -> c_int {
scanf::scanf(file, format, ap)
scanf::scanf(file.lock(), format, ap)
}
#[no_mangle]
+8 -4
View File
@@ -39,11 +39,15 @@ unsafe fn inner_scanf<R: Read>(
macro_rules! read {
() => {{
let n = r.read_u8(&mut byte);
if n {
count += 1;
match r.read_u8() {
Ok(Some(b)) => {
byte = b;
count += 1;
true
},
Ok(None) => false,
Err(()) => return Err(-1)
}
n
}};
}