Skip to content

Commit

Permalink
Add filetype syscall (#655)
Browse files Browse the repository at this point in the history
* Implement TryFrom for FileType

* Use TryFrom in FileInfo

* Add new KIND syscall

* Add api::io::is_redirected

* Use detection of redirection in hash command

* Update website doc
  • Loading branch information
vinc committed Sep 14, 2024
1 parent 7cedcfc commit 2f5bb90
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 19 deletions.
6 changes: 6 additions & 0 deletions doc/syscalls.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
8 changes: 8 additions & 0 deletions src/api/io.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::api::syscall;
use crate::sys::fs::FileType;

use alloc::string::{String, ToString};
use alloc::vec;
Expand Down Expand Up @@ -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,
}
}
12 changes: 11 additions & 1 deletion src/api/syscall.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -39,6 +40,15 @@ pub fn info(path: &str) -> Option<FileInfo> {
}
}

pub fn kind(handle: usize) -> Option<FileType> {
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<usize> {
let ptr = path.as_ptr() as usize;
let len = path.len();
Expand Down
8 changes: 1 addition & 7 deletions src/sys/fs/dir_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
24 changes: 24 additions & 0 deletions src/sys/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -102,13 +103,36 @@ pub enum FileType {
Device = 2,
}

impl TryFrom<usize> for FileType {
type Error = ();

fn try_from(num: usize) -> Result<Self, Self::Error> {
match num {
0 => Ok(FileType::Dir),
1 => Ok(FileType::File),
2 => Ok(FileType::Device),
_ => Err(()),
}
}
}

#[derive(Debug, Clone)]
pub enum Resource {
Dir(Dir),
File(File),
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<usize, ()> {
match self {
Expand Down
4 changes: 4 additions & 0 deletions src/sys/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/sys/syscall/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
8 changes: 8 additions & 0 deletions src/sys/syscall/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
34 changes: 23 additions & 11 deletions src/usr/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,37 @@ 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> {
let mut i = 1;
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" => {
help();
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('-') {
Expand All @@ -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) {
Expand All @@ -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::<Vec<String>>().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();
Expand Down
5 changes: 5 additions & 0 deletions www/syscalls.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ <h2>FREE (0x11)</h2>

<pre><code class="rust">pub fn free(ptr: *mut u8, size: usize, align: usize)
</code></pre>

<h2>KIND (0x12)</h2>

<pre><code class="rust">pub fn kind(handle: usize) -&gt; isize
</code></pre>
<footer><p><a href="/">MOROS</a></footer>
</body>
</html>

0 comments on commit 2f5bb90

Please sign in to comment.