diff --git a/doc/syscalls.md b/doc/syscalls.md index 59fa17e1e..2b641552b 100644 --- a/doc/syscalls.md +++ b/doc/syscalls.md @@ -105,3 +105,9 @@ pub fn alloc(size: usize, align: usize) -> *mut u8 ```rust pub fn free(ptr: *mut u8, size: usize, align: usize) ``` + +## KIND (0x12) + +```rust +pub fn kind(handle: usize) -> isize +``` diff --git a/src/api/io.rs b/src/api/io.rs index f6ec8423a..44af028ea 100644 --- a/src/api/io.rs +++ b/src/api/io.rs @@ -1,4 +1,5 @@ use crate::api::syscall; +use crate::sys::fs::FileType; use alloc::string::{String, ToString}; use alloc::vec; @@ -66,3 +67,10 @@ pub fn stdout() -> Stdout { pub fn stderr() -> Stderr { Stderr::new() } + +pub fn is_redirected(handle: usize) -> bool { + match syscall::kind(handle) { + Some(FileType::File) => true, + _ => false, + } +} diff --git a/src/api/syscall.rs b/src/api/syscall.rs index 2bdf0a2c1..667837117 100644 --- a/src/api/syscall.rs +++ b/src/api/syscall.rs @@ -1,9 +1,10 @@ use crate::api::fs::IO; use crate::api::process::ExitCode; -use crate::sys::fs::FileInfo; +use crate::sys::fs::{FileInfo, FileType}; use crate::sys::syscall::number::*; use crate::syscall; +use core::convert::TryFrom; use smoltcp::wire::IpAddress; use smoltcp::wire::Ipv4Address; @@ -39,6 +40,15 @@ pub fn info(path: &str) -> Option { } } +pub fn kind(handle: usize) -> Option { + let res = unsafe { syscall!(KIND, handle) } as isize; + if res >= 0 { + FileType::try_from(res as usize).ok() + } else { + None + } +} + pub fn open(path: &str, flags: usize) -> Option { let ptr = path.as_ptr() as usize; let len = path.len(); diff --git a/src/sys/fs/dir_entry.rs b/src/sys/fs/dir_entry.rs index 5f5197eb3..499a1dc67 100644 --- a/src/sys/fs/dir_entry.rs +++ b/src/sys/fs/dir_entry.rs @@ -180,13 +180,7 @@ impl FileInfo { impl From<&[u8]> for FileInfo { fn from(buf: &[u8]) -> Self { - let kind = match buf[0] { - // TODO: Add FileType::from(u8) - 0 => FileType::Dir, - 1 => FileType::File, - 2 => FileType::Device, - _ => panic!(), - }; + let kind = (buf[0] as usize).try_into().unwrap(); let size = u32::from_be_bytes(buf[1..5].try_into().unwrap()); let time = u64::from_be_bytes(buf[5..13].try_into().unwrap()); let i = 14 + buf[13] as usize; diff --git a/src/sys/fs/mod.rs b/src/sys/fs/mod.rs index 992d9c6c9..53350f696 100644 --- a/src/sys/fs/mod.rs +++ b/src/sys/fs/mod.rs @@ -25,6 +25,7 @@ use dir_entry::DirEntry; use super_block::SuperBlock; use alloc::string::{String, ToString}; +use core::convert::TryFrom; pub const VERSION: u8 = 2; @@ -102,6 +103,19 @@ pub enum FileType { Device = 2, } +impl TryFrom for FileType { + type Error = (); + + fn try_from(num: usize) -> Result { + match num { + 0 => Ok(FileType::Dir), + 1 => Ok(FileType::File), + 2 => Ok(FileType::Device), + _ => Err(()), + } + } +} + #[derive(Debug, Clone)] pub enum Resource { Dir(Dir), @@ -109,6 +123,16 @@ pub enum Resource { Device(Device), } +impl Resource { + pub fn kind(&self) -> FileType { + match self { + Resource::Dir(_) => FileType::Dir, + Resource::File(_) => FileType::File, + Resource::Device(_) => FileType::Device, + } + } +} + impl FileIO for Resource { fn read(&mut self, buf: &mut [u8]) -> Result { match self { diff --git a/src/sys/syscall/mod.rs b/src/sys/syscall/mod.rs index 1694aec8d..a7b7a2446 100644 --- a/src/sys/syscall/mod.rs +++ b/src/sys/syscall/mod.rs @@ -42,6 +42,10 @@ pub fn dispatcher( let info = unsafe { &mut *(arg3 as *mut FileInfo) }; service::info(path, info) as usize } + number::KIND => { + let handle = arg1; + service::kind(handle) as usize + } number::OPEN => { let ptr = sys::process::ptr_from_addr(arg1 as u64); let len = arg2; diff --git a/src/sys/syscall/number.rs b/src/sys/syscall/number.rs index 9b0a80415..7b3623783 100644 --- a/src/sys/syscall/number.rs +++ b/src/sys/syscall/number.rs @@ -15,3 +15,4 @@ pub const LISTEN: usize = 0xE; pub const ACCEPT: usize = 0xF; pub const ALLOC: usize = 0x10; pub const FREE: usize = 0x11; +pub const KIND: usize = 0x12; diff --git a/src/sys/syscall/service.rs b/src/sys/syscall/service.rs index 508a7c079..b834eadf7 100644 --- a/src/sys/syscall/service.rs +++ b/src/sys/syscall/service.rs @@ -41,6 +41,14 @@ pub fn info(path: &str, info: &mut FileInfo) -> isize { } } +pub fn kind(handle: usize) -> isize { + if let Some(file) = sys::process::handle(handle) { + file.kind() as isize + } else { + -1 + } +} + pub fn open(path: &str, flags: usize) -> isize { let path = match sys::fs::canonicalize(path) { Ok(path) => path, diff --git a/src/usr/hash.rs b/src/usr/hash.rs index 1a689d311..7cd0a68f9 100644 --- a/src/usr/hash.rs +++ b/src/usr/hash.rs @@ -11,8 +11,9 @@ use sha2::{Digest, Sha256}; #[derive(Copy, Clone)] struct Config { - show_full_hash: bool, - recursive_mode: bool, + colorized: bool, + full_hash: bool, + recursive: bool, } pub fn main(args: &[&str]) -> Result<(), ExitCode> { @@ -20,9 +21,13 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { let n = args.len(); let mut paths = Vec::new(); let mut conf = Config { - show_full_hash: false, - recursive_mode: false, + colorized: true, + full_hash: false, + recursive: false, }; + if api::io::is_redirected(1) { + conf.colorized = false; + } while i < n { match args[i] { "-h" | "--help" => { @@ -30,10 +35,13 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { return Ok(()); } "-f" | "--full" => { - conf.show_full_hash = true; + conf.full_hash = true; } "-r" | "--recursive" => { - conf.recursive_mode = true; + conf.recursive = true; + } + "--color" => { + conf.colorized = true; } arg => { if arg.starts_with('-') { @@ -59,7 +67,9 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { } fn print_hash(path: &str, conf: Config) -> Result<(), ExitCode> { - let n = if conf.show_full_hash { 32 } else { 16 }; + let color = Style::color("fushia"); + let reset = Style::reset(); + let n = if conf.full_hash { 32 } else { 16 }; if let Some(info) = syscall::info(path) { if info.is_file() { if let Ok(bytes) = api::fs::read_to_bytes(path) { @@ -69,15 +79,17 @@ fn print_hash(path: &str, conf: Config) -> Result<(), ExitCode> { let hex = res.iter().map(|byte| format!("{:02X}", byte) ).take(n).collect::>().join(""); - let pink = Style::color("fushia"); - let reset = Style::reset(); - println!("{}{}{} {}", pink, hex, reset, path); + if conf.colorized { + println!("{}{}{} {}", color, hex, reset, path); + } else { + println!("{} {}", hex, path); + } Ok(()) } else { error!("Could not read '{}'", path); Err(ExitCode::Failure) } - } else if conf.recursive_mode && info.is_dir() { + } else if conf.recursive && info.is_dir() { if let Ok(entries) = api::fs::read_dir(path) { let mut fs: Vec<_> = entries.iter().map(|e| e.name()).collect(); fs.sort(); diff --git a/www/syscalls.html b/www/syscalls.html index dc9305647..9397fdcf6 100644 --- a/www/syscalls.html +++ b/www/syscalls.html @@ -96,6 +96,11 @@

FREE (0x11)

pub fn free(ptr: *mut u8, size: usize, align: usize)
 
+ +

KIND (0x12)

+ +
pub fn kind(handle: usize) -> isize
+