Skip to content

Commit

Permalink
Fix various issues while reading files (#307)
Browse files Browse the repository at this point in the history
* Define device file buffer in kernel

* Implement from u8 for Device

* Reading /dev/null result in error

* Reading an empty dir should not result in error

* Print all bytes from reading devices

* Print errors while reading devices

* Handle ^C and ^D when reading /dev/console

* Create pseudo device files for clocks

* Avoid hardcoding ^C and ^D

* Add missing comment
  • Loading branch information
vinc authored Jan 25, 2022
1 parent d06f641 commit f044066
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 22 deletions.
2 changes: 2 additions & 0 deletions src/api/console.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::sys;
use core::fmt;

pub use crate::sys::console::{ETX_KEY, EOT_KEY};

#[derive(Clone, Copy)]
pub struct Style {
foreground: Option<usize>,
Expand Down
3 changes: 1 addition & 2 deletions src/api/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ pub fn open_device(path: &str) -> Option<usize> {
pub fn create_device(path: &str, kind: DeviceType) -> Option<usize> {
let flags = OpenFlag::Create as usize | OpenFlag::Device as usize;
if let Some(handle) = syscall::open(path, flags) {
let buf = [kind as u8; 1];
syscall::write(handle, &buf);
syscall::write(handle, &kind.buf());
return Some(handle);
}
None
Expand Down
4 changes: 2 additions & 2 deletions src/api/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ impl Prompt {
let mut parser = Parser::new();
while let Some(c) = io::stdin().read_char() {
match c {
'\x03' => { // End of Text (^C)
console::ETX_KEY => { // End of Text (^C)
println!();
return Some(String::new());
},
'\x04' => { // End of Transmission (^D)
console::EOT_KEY => { // End of Transmission (^D)
println!();
return None;
},
Expand Down
8 changes: 4 additions & 4 deletions src/sys/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ pub fn is_raw_enabled() -> bool {
*RAW.lock()
}

const ETX_KEY: char = '\x03'; // End of Text
const EOT_KEY: char = '\x04'; // End of Transmission
const BS_KEY: char = '\x08'; // Backspace
const ESC_KEY: char = '\x1B'; // Escape
pub const ETX_KEY: char = '\x03'; // End of Text
pub const EOT_KEY: char = '\x04'; // End of Transmission
pub const BS_KEY: char = '\x08'; // Backspace
pub const ESC_KEY: char = '\x1B'; // Escape

pub fn key_handle(key: char) {
let mut stdin = STDIN.lock();
Expand Down
23 changes: 19 additions & 4 deletions src/sys/fs/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ use super::dir::Dir;
use super::file::File;
use super::block::LinkedBlock;

use alloc::vec;
use alloc::vec::Vec;
use crate::sys::console::Console;
use crate::sys::random::Random;

#[derive(PartialEq, Clone, Copy)]
#[repr(u8)]
pub enum DeviceType {
File = 0,
Expand All @@ -14,6 +17,16 @@ pub enum DeviceType {
Null = 3,
}

impl DeviceType {
pub fn buf(self) -> Vec<u8> {
if self == DeviceType::Console {
vec![self as u8, 0, 0, 0] // 4 bytes
} else {
vec![self as u8] // 1 byte
}
}
}

#[derive(Debug, Clone)]
pub enum Device {
File(File),
Expand All @@ -22,16 +35,18 @@ pub enum Device {
Null,
}

impl Device {
fn new(i: u8) -> Self {
impl From<u8> for Device {
fn from(i: u8) -> Self {
match i {
i if i == DeviceType::Console as u8 => Device::Console(Console::new()),
i if i == DeviceType::Random as u8 => Device::Random(Random::new()),
i if i == DeviceType::Null as u8 => Device::Null,
_ => unimplemented!(),
}
}
}

impl Device {
pub fn create(pathname: &str) -> Option<Self> {
let pathname = realpath(pathname);
let dirname = dirname(&pathname);
Expand All @@ -53,7 +68,7 @@ impl Device {
if dir_entry.is_device() {
let block = LinkedBlock::read(dir_entry.addr());
let data = block.data();
return Some(Self::new(data[0]));
return Some(data[0].into());
}
}
}
Expand All @@ -67,7 +82,7 @@ impl FileIO for Device {
Device::File(io) => io.read(buf),
Device::Console(io) => io.read(buf),
Device::Random(io) => io.read(buf),
Device::Null => Ok(0),
Device::Null => Err(()),
}
}
fn write(&mut self, buf: &[u8]) -> Result<usize, ()> {
Expand Down
6 changes: 1 addition & 5 deletions src/sys/fs/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,7 @@ impl FileIO for Dir {
break;
}
}
if i > 0 {
Ok(i)
} else {
Err(())
}
Ok(i)
}
fn write(&mut self, _buf: &[u8]) -> Result<usize, ()> {
Err(())
Expand Down
3 changes: 3 additions & 0 deletions src/usr/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub fn copy_files(verbose: bool) {
copy_file("/bin/sleep", include_bytes!("../../dsk/bin/sleep"), verbose);

create_dir("/dev/clk", verbose); // Clocks
create_dev("/dev/clk/uptime", DeviceType::File, verbose); // TODO
create_dev("/dev/clk/realtime", DeviceType::File, verbose); // TODO
create_dev("/dev/rtc", DeviceType::File, verbose); // TODO
create_dev("/dev/null", DeviceType::Null, verbose);
create_dev("/dev/random", DeviceType::Random, verbose);
create_dev("/dev/console", DeviceType::Console, verbose);
Expand Down
4 changes: 2 additions & 2 deletions src/usr/pow.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::usr;
use crate::api::console::Style;
use crate::api::{io, random};
use crate::api::{io, random, console};
use core::fmt;
use alloc::format;
use alloc::string::ToString;
Expand Down Expand Up @@ -34,7 +34,7 @@ impl Game {
let mut parser = Parser::new();
while let Some(c) = io::stdin().read_char() {
match c {
'q' | '\x03' | '\x04' => { // ^C and ^D
'q' | console::ETX_KEY | console::EOT_KEY => {
return;
},
c => {
Expand Down
28 changes: 25 additions & 3 deletions src/usr/read.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::{api, sys, usr};
use crate::api::console;
use crate::api::fs;
use crate::api::syscall;
use crate::sys::cmos::CMOS;

use alloc::borrow::ToOwned;
use alloc::vec::Vec;

Expand All @@ -18,6 +20,7 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
path = path.trim_end_matches('/');
}

// TODO: Create device drivers for `/dev` and `/net` hardcoded commands
match path {
"/dev/rtc" => {
let rtc = CMOS::new().rtc();
Expand Down Expand Up @@ -81,14 +84,33 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
} else if info.is_dir() {
usr::list::main(args)
} else if info.is_device() {
let is_console = info.size() == 4; // TODO: Improve device detection
loop {
if let Ok(bytes) = fs::read_to_bytes(path) {
print!("{}", bytes[0] as char);
}
if sys::console::end_of_text() {
println!();
return usr::shell::ExitCode::CommandSuccessful;
}
if let Ok(bytes) = fs::read_to_bytes(path) {
if is_console && bytes.len() == 1 {
match bytes[0] as char {
console::ETX_KEY => {
println!("^C");
return usr::shell::ExitCode::CommandSuccessful;
}
console::EOT_KEY => {
println!("^D");
return usr::shell::ExitCode::CommandSuccessful;
}
_ => {}
}
}
for b in bytes {
print!("{}", b as char);
}
} else {
eprintln!("Could not read '{}'", path);
return usr::shell::ExitCode::CommandError;
}
}
} else {
eprintln!("Could not read type of '{}'", path);
Expand Down

0 comments on commit f044066

Please sign in to comment.