Skip to content
Snippets Groups Projects
Verified Commit 90c6937f authored by Tom Almeida's avatar Tom Almeida
Browse files

Changed FILE to use a vector as a buffer instead of raw pointers. This allows...

Changed FILE to use a vector as a buffer instead of raw pointers. This allows us to remove the large majority of unsafe blocks from the code
parent ccb74c6e
No related branches found
No related tags found
1 merge request!136Fixing some things in stdio
...@@ -33,6 +33,26 @@ use types::*; ...@@ -33,6 +33,26 @@ use types::*;
#[no_mangle] #[no_mangle]
pub static mut errno: c_int = 0; pub static mut errno: c_int = 0;
pub unsafe fn c_str_mut<'a>(s: *mut c_char) -> &'a mut [u8] {
use core::usize;
c_str_n_mut(s, usize::MAX)
}
pub unsafe fn c_str_n_mut<'a>(s: *mut c_char, n: usize) -> &'a mut [u8] {
use core::slice;
let mut size = 0;
for _ in 0..n {
if *s.offset(size) == 0 {
break;
}
size += 1;
}
slice::from_raw_parts_mut(s as *mut u8, size as usize)
}
pub unsafe fn c_str<'a>(s: *const c_char) -> &'a [u8] { pub unsafe fn c_str<'a>(s: *const c_char) -> &'a [u8] {
use core::usize; use core::usize;
......
...@@ -8,9 +8,11 @@ build = "build.rs" ...@@ -8,9 +8,11 @@ build = "build.rs"
cbindgen = { path = "../../cbindgen" } cbindgen = { path = "../../cbindgen" }
[dependencies] [dependencies]
platform = { path = "../platform" } errno = { path = "../errno"}
va_list = { path = "../../va_list", features = ["no_std"] }
fcntl = { path = "../fcntl" } fcntl = { path = "../fcntl" }
lazy_static = "*"
platform = { path = "../platform" }
ralloc = { path = "../../ralloc" }
string = { path = "../string" } string = { path = "../string" }
stdlib = { path = "../stdlib" } stdlib = { path = "../stdlib" }
errno = { path = "../errno"} va_list = { path = "../../va_list", features = ["no_std"] }
use core::sync::atomic::AtomicBool; use core::sync::atomic::AtomicBool;
use core::ptr; use super::{constants, BUFSIZ, FILE, UNGET};
use super::{constants, internal, BUFSIZ, FILE, UNGET};
lazy_static! {
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
static mut default_stdin_buf: [u8; BUFSIZ as usize + UNGET] = [0; BUFSIZ as usize + UNGET]; static ref default_stdin: FILE = FILE {
flags: constants::F_PERM | constants::F_NOWR | constants::F_BADJ,
#[allow(non_upper_case_globals)] read: None,
static mut default_stdin: FILE = FILE { write: None,
flags: constants::F_PERM | constants::F_NOWR | constants::F_BADJ, fd: 0,
rpos: ptr::null_mut(), buf: vec![0u8;(BUFSIZ + UNGET) as usize],
rend: ptr::null_mut(), buf_char: -1,
wend: ptr::null_mut(), unget: UNGET,
wpos: ptr::null_mut(), lock: AtomicBool::new(false),
wbase: ptr::null_mut(), };
fd: 0,
buf: unsafe { &mut default_stdin_buf as *mut [u8] as *mut u8 }, #[allow(non_upper_case_globals)]
buf_size: BUFSIZ as usize, static ref default_stdout: FILE = FILE {
buf_char: -1, flags: constants::F_PERM | constants::F_NORD | constants::F_BADJ,
unget: UNGET, read: None,
lock: AtomicBool::new(false), write: None,
}; fd: 1,
buf: vec![0u8;(BUFSIZ + UNGET) as usize],
#[allow(non_upper_case_globals)] buf_char: b'\n' as i8,
static mut default_stdout_buf: [u8; BUFSIZ as usize] = [0; BUFSIZ as usize]; unget: 0,
lock: AtomicBool::new(false),
#[allow(non_upper_case_globals)] };
static mut default_stdout: FILE = FILE {
flags: constants::F_PERM | constants::F_NORD | constants::F_BADJ, #[allow(non_upper_case_globals)]
rpos: ptr::null_mut(), static ref default_stderr: FILE = FILE {
rend: ptr::null_mut(), flags: constants::F_PERM | constants::F_NORD | constants::F_BADJ,
wend: ptr::null_mut(), read: None,
wpos: ptr::null_mut(), write: None,
wbase: ptr::null_mut(), fd: 2,
fd: 1, buf: vec![0u8;(BUFSIZ + UNGET) as usize],
buf: unsafe { &mut default_stdout_buf } as *mut [u8] as *mut u8, buf_char: -1,
buf_size: BUFSIZ as usize, unget: 0,
buf_char: b'\n' as i8, lock: AtomicBool::new(false),
unget: 0, };
lock: AtomicBool::new(false), }
};
#[allow(non_upper_case_globals)]
static mut default_stderr_buf: [u8; BUFSIZ as usize] = [0; BUFSIZ as usize];
#[allow(non_upper_case_globals)]
static mut default_stderr: FILE = FILE {
flags: constants::F_PERM | constants::F_NORD | constants::F_BADJ,
rpos: ptr::null_mut(),
rend: ptr::null_mut(),
wend: ptr::null_mut(),
wpos: ptr::null_mut(),
wbase: ptr::null_mut(),
fd: 2,
buf: unsafe { &mut default_stderr_buf } as *mut [u8] as *mut u8,
buf_size: BUFSIZ as usize,
buf_char: -1,
unget: 0,
lock: AtomicBool::new(false),
};
// Don't ask me how the casting below works, I have no idea // Don't ask me how the casting below works, I have no idea
// " as *const FILE as *mut FILE" rust pls // " as *const FILE as *mut FILE" rust pls
// //
// -- Tommoa // -- Tommoa
#[allow(non_upper_case_globals)]
#[no_mangle] #[no_mangle]
pub static mut stdin: *mut FILE = unsafe { &default_stdin } as *const FILE as *mut FILE; pub static mut stdin: *mut FILE = &default_stdin as *const _ as *const FILE as *mut FILE;
#[allow(non_upper_case_globals)]
#[no_mangle] #[no_mangle]
pub static mut stdout: *mut FILE = unsafe { &default_stdout } as *const FILE as *mut FILE; pub static mut stdout: *mut FILE = &default_stdout as *const _ as *const FILE as *mut FILE;
#[allow(non_upper_case_globals)]
#[no_mangle] #[no_mangle]
pub static mut stderr: *mut FILE = unsafe { &default_stderr } as *const FILE as *mut FILE; pub static mut stderr: *mut FILE = &default_stderr as *const _ as *const FILE as *mut FILE;
use super::{internal, BUFSIZ, FILE, UNGET}; use super::{BUFSIZ, FILE, UNGET};
use stdlib::calloc;
use core::{mem, ptr};
use core::sync::atomic::AtomicBool; use core::sync::atomic::AtomicBool;
use platform::types::*; use platform::types::*;
use super::constants::*; use super::constants::*;
...@@ -38,11 +36,11 @@ pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 { ...@@ -38,11 +36,11 @@ pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 {
} }
/// Open a file with the file descriptor `fd` in the mode `mode` /// Open a file with the file descriptor `fd` in the mode `mode`
pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> *mut FILE { pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<FILE> {
use string::strchr; use string::strchr;
if *mode != b'r' as i8 && *mode != b'w' as i8 && *mode != b'a' as i8 { if *mode != b'r' as i8 && *mode != b'w' as i8 && *mode != b'a' as i8 {
platform::errno = errno::EINVAL; platform::errno = errno::EINVAL;
return ptr::null_mut(); return None;
} }
let mut flags = 0; let mut flags = 0;
...@@ -62,23 +60,17 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> *mut FILE { ...@@ -62,23 +60,17 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
flags |= F_APP; flags |= F_APP;
} }
let file = calloc(mem::size_of::<FILE>() + BUFSIZ + UNGET, 1) as *mut FILE;
// Allocate the file // Allocate the file
(*file) = FILE { Some(FILE {
flags: flags, flags: flags,
rpos: ptr::null_mut(), read: None,
rend: ptr::null_mut(), write: None,
wend: ptr::null_mut(),
wpos: ptr::null_mut(),
wbase: ptr::null_mut(),
fd: fd, fd: fd,
buf: (file as *mut u8).add(mem::size_of::<FILE>() + UNGET), buf: vec![0u8; BUFSIZ + UNGET],
buf_size: BUFSIZ,
buf_char: -1, buf_char: -1,
unget: UNGET, unget: UNGET,
lock: AtomicBool::new(false), lock: AtomicBool::new(false),
}; })
file
} }
/// Write buffer `buf` of length `l` into `stream` /// Write buffer `buf` of length `l` into `stream`
...@@ -90,58 +82,68 @@ pub fn fwritex(buf: *const u8, l: size_t, stream: &mut FILE) -> size_t { ...@@ -90,58 +82,68 @@ pub fn fwritex(buf: *const u8, l: size_t, stream: &mut FILE) -> size_t {
let mut l = l; let mut l = l;
let mut advance = 0; let mut advance = 0;
if stream.wend.is_null() && !stream.can_write() { if stream.write.is_none() && !stream.can_write() {
// We can't write to this stream // We can't write to this stream
return 0; return 0;
} }
if l > stream.wend as usize - stream.wpos as usize { if let Some((wbase, wpos, wend)) = stream.write {
// We can't fit all of buf in the buffer if l > wend - wpos {
return stream.write(buf); // We can't fit all of buf in the buffer
} return stream.write(buf);
let i = if stream.buf_char >= 0 {
let mut i = l;
while i > 0 && buf[i - 1] != b'\n' {
i -= 1;
} }
if i > 0 {
let n = stream.write(buf); let i = if stream.buf_char >= 0 {
if n < i { let mut i = l;
return n; while i > 0 && buf[i - 1] != b'\n' {
i -= 1;
}
if i > 0 {
let n = stream.write(buf);
if n < i {
return n;
}
advance += i;
l -= i;
} }
advance += i; i
l -= i; } else {
0
};
unsafe {
copy_nonoverlapping(
&buf[advance..] as *const _ as *const u8,
&mut stream.buf[wpos..] as *mut _ as *mut u8,
l,
);
} }
i stream.write = Some((wbase, wpos + l, wend));
l + i
} else { } else {
0 0
};
unsafe {
// Copy and reposition
copy_nonoverlapping(&buf[advance..] as *const _ as *const u8, stream.wpos, l);
stream.wpos = stream.wpos.add(l);
} }
l + i
} }
/// Flush `stream` without locking it. /// Flush `stream` without locking it.
pub fn fflush_unlocked(stream: &mut FILE) -> c_int { pub fn fflush_unlocked(stream: &mut FILE) -> c_int {
if stream.wpos > stream.wbase { if let Some((wbase, wpos, _)) = stream.write {
stream.write(&[]); if wpos > wbase {
if stream.wpos.is_null() { stream.write(&[]);
/*
if stream.wpos.is_null() {
return -1; return -1;
}
*/
} }
} }
if stream.rpos < stream.rend { if let Some((rpos, rend)) = stream.read {
stream.seek(stream.rpos as i64 - stream.rend as i64, SEEK_CUR); if rpos < rend {
stream.seek(rpos as i64 - rend as i64, SEEK_CUR);
}
} }
stream.wpos = ptr::null_mut(); stream.write = None;
stream.wend = ptr::null_mut(); stream.read = None;
stream.wbase = ptr::null_mut();
stream.rpos = ptr::null_mut();
stream.rend = ptr::null_mut();
0 0
} }
use super::{constants, FILE}; use super::{constants, FILE};
use platform;
use platform::types::*; use platform::types::*;
use core::{mem, ptr, slice};
pub fn ftello(stream: &mut FILE) -> off_t { pub fn ftello(stream: &mut FILE) -> off_t {
let pos = stream.seek( let pos = stream.seek(
0, 0,
if (stream.flags & constants::F_APP > 0) && stream.wpos > stream.wbase { if let Some((wbase, wpos, _)) = stream.write {
constants::SEEK_END if (stream.flags & constants::F_APP > 0) && wpos > wbase {
constants::SEEK_END
} else {
constants::SEEK_CUR
}
} else { } else {
constants::SEEK_CUR constants::SEEK_CUR
}, },
...@@ -15,5 +17,15 @@ pub fn ftello(stream: &mut FILE) -> off_t { ...@@ -15,5 +17,15 @@ pub fn ftello(stream: &mut FILE) -> off_t {
if pos < 0 { if pos < 0 {
return pos; return pos;
} }
pos - (stream.rend as i64 - stream.rpos as i64) + (stream.wpos as i64 - stream.wbase as i64) let rdiff = if let Some((rpos, rend)) = stream.read {
rend - rpos
} else {
0
};
let wdiff = if let Some((wbase, wpos, _)) = stream.write {
wpos - wbase
} else {
0
};
pos - rdiff as i64 + wdiff as i64
} }
This diff is collapsed.
use core::{fmt, slice, str}; use core::{slice, str};
use platform::{self, Write}; use platform::{self, Write};
use platform::types::*; use platform::types::*;
...@@ -17,90 +17,91 @@ pub unsafe fn printf<W: Write>(mut w: W, format: *const c_char, mut ap: VaList) ...@@ -17,90 +17,91 @@ pub unsafe fn printf<W: Write>(mut w: W, format: *const c_char, mut ap: VaList)
if found_percent { if found_percent {
match b as char { match b as char {
'%' => { '%' => {
w.write_char('%');
found_percent = false; found_percent = false;
w.write_char('%')
} }
'c' => { 'c' => {
let a = ap.get::<u32>(); let a = ap.get::<u32>();
w.write_u8(a as u8);
found_percent = false; found_percent = false;
w.write_u8(a as u8)
} }
'd' | 'i' => { 'd' | 'i' => {
let a = ap.get::<c_int>(); let a = ap.get::<c_int>();
w.write_fmt(format_args!("{}", a));
found_percent = false; found_percent = false;
w.write_fmt(format_args!("{}", a))
} }
'f' | 'F' => { 'f' | 'F' => {
let a = ap.get::<f64>(); let a = ap.get::<f64>();
w.write_fmt(format_args!("{}", a));
found_percent = false; found_percent = false;
w.write_fmt(format_args!("{}", a))
} }
'n' => { 'n' => {
let _a = ap.get::<c_int>(); let _a = ap.get::<c_int>();
found_percent = false; found_percent = false;
Ok(())
} }
'p' => { 'p' => {
let a = ap.get::<usize>(); let a = ap.get::<usize>();
w.write_fmt(format_args!("0x{:x}", a));
found_percent = false; found_percent = false;
w.write_fmt(format_args!("0x{:x}", a))
} }
's' => { 's' => {
let a = ap.get::<usize>(); let a = ap.get::<usize>();
found_percent = false;
w.write_str(str::from_utf8_unchecked(platform::c_str( w.write_str(str::from_utf8_unchecked(platform::c_str(
a as *const c_char, a as *const c_char,
))); )))
found_percent = false;
} }
'u' => { 'u' => {
let a = ap.get::<c_uint>(); let a = ap.get::<c_uint>();
w.write_fmt(format_args!("{}", a));
found_percent = false; found_percent = false;
w.write_fmt(format_args!("{}", a))
} }
'x' => { 'x' => {
let a = ap.get::<c_uint>(); let a = ap.get::<c_uint>();
w.write_fmt(format_args!("{:x}", a));
found_percent = false; found_percent = false;
w.write_fmt(format_args!("{:x}", a))
} }
'X' => { 'X' => {
let a = ap.get::<c_uint>(); let a = ap.get::<c_uint>();
w.write_fmt(format_args!("{:X}", a));
found_percent = false; found_percent = false;
w.write_fmt(format_args!("{:X}", a))
} }
'o' => { 'o' => {
let a = ap.get::<c_uint>(); let a = ap.get::<c_uint>();
w.write_fmt(format_args!("{:o}", a));
found_percent = false; found_percent = false;
w.write_fmt(format_args!("{:o}", a))
} }
'-' => {} '-' => Ok(()),
'+' => {} '+' => Ok(()),
' ' => {} ' ' => Ok(()),
'#' => {} '#' => Ok(()),
'0'...'9' => {} '0'...'9' => Ok(()),
_ => {} _ => Ok(()),
} }.expect("Error writing!")
} else if b == b'%' { } else if b == b'%' {
found_percent = true; found_percent = true;
} else { } else {
w.write_u8(b); w.write_u8(b).expect("Error writing char!");
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment