diff --git a/Makefile b/Makefile index ba8bb46..5622ef9 100644 --- a/Makefile +++ b/Makefile @@ -98,6 +98,8 @@ initrd: cp target/$(ARCH)-osdev5/$(PROFILE)/shell $(O)/rootfs/bin cp target/$(ARCH)-osdev5/$(PROFILE)/fuzzy $(O)/rootfs/bin cp target/$(ARCH)-osdev5/$(PROFILE)/ls $(O)/rootfs/bin + cp target/$(ARCH)-osdev5/$(PROFILE)/cat $(O)/rootfs/bin + cp target/$(ARCH)-osdev5/$(PROFILE)/hexd $(O)/rootfs/bin cp target/$(ARCH)-osdev5/$(PROFILE)/login $(O)/rootfs/sbin cd $(O)/rootfs && tar cf ../initrd.img `find -type f -printf "%P\n"` ifeq ($(MACH),orangepi3) diff --git a/libusr/src/file.rs b/libusr/src/file.rs index 7603252..6c1855e 100644 --- a/libusr/src/file.rs +++ b/libusr/src/file.rs @@ -1,13 +1,18 @@ -use crate::io::{AsRawFd, Error}; -use libsys::stat::FileDescriptor; +use crate::io::{AsRawFd, Error, Read, Write}; +use libsys::{ + calls::{sys_openat, sys_read, sys_close}, + stat::{FileDescriptor, FileMode, OpenFlags}, +}; pub struct File { fd: FileDescriptor, } impl File { - pub fn open(_path: &str) -> Result { - todo!() + pub fn open(path: &str) -> Result { + let fd = sys_openat(None, path, FileMode::default_reg(), OpenFlags::O_RDONLY) + .map_err(Error::from)?; + Ok(File { fd }) } } @@ -19,6 +24,12 @@ impl AsRawFd for File { impl Drop for File { fn drop(&mut self) { - todo!(); + sys_close(self.fd).ok(); + } +} + +impl Read for File { + fn read(&mut self, bytes: &mut [u8]) -> Result { + sys_read(self.fd, bytes).map_err(Error::from) } } diff --git a/user/Cargo.toml b/user/Cargo.toml index 2c41d63..910a7e6 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -21,6 +21,14 @@ path = "src/bin/fuzzy.rs" name = "ls" path = "src/bin/ls.rs" +[[bin]] +name = "cat" +path = "src/bin/cat.rs" + +[[bin]] +name = "hexd" +path = "src/bin/hexd.rs" + [[bin]] name = "login" path = "src/sbin/login.rs" diff --git a/user/src/bin/cat.rs b/user/src/bin/cat.rs new file mode 100644 index 0000000..24e2592 --- /dev/null +++ b/user/src/bin/cat.rs @@ -0,0 +1,48 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate libusr; +#[macro_use] +extern crate alloc; + +use libusr::io::{self, Read, Write}; +use libusr::file::File; + +fn do_cat(mut fd: F) -> Result<(), io::Error> { + let mut buf = [0; 4096]; + let mut out = io::stdout(); + + loop { + let count = fd.read(&mut buf)?; + if count == 0 { + break; + } + + out.write(&buf[..count]); + } + + Ok(()) +} + +#[no_mangle] +fn main() -> i32 { + let args = libusr::env::args(); + let mut res = 0; + + if args.len() == 1 { + if let Err(e) = do_cat(io::stdin()) { + eprintln!("{}: {:?}", ".", e); + res = -1; + } + } else { + for arg in &args[1..] { + if let Err(e) = File::open(arg).map(do_cat) { + eprintln!("{}: {:?}", arg, e); + res = -1; + } + } + } + + res +} diff --git a/user/src/bin/hexd.rs b/user/src/bin/hexd.rs new file mode 100644 index 0000000..0a2b1cd --- /dev/null +++ b/user/src/bin/hexd.rs @@ -0,0 +1,71 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate libusr; +#[macro_use] +extern crate alloc; + +use libusr::io::{self, Read, Write}; +use libusr::file::File; + +fn line_print(off: usize, line: &[u8]) { + print!("{:08x}: ", off); + for i in 0..16 { + if i < line.len() { + print!("{:02x}", line[i]); + } else { + print!(" "); + } + if i % 2 != 0 { + print!(" "); + } + } + print!("| "); + for &b in line.iter() { + if b.is_ascii() && !b.is_ascii_control() { + print!("{}", b as char); + } else { + print!("."); + } + } + println!(""); +} + +fn do_hexd(mut fd: F) -> Result<(), io::Error> { + let mut buf = [0; 16]; + let mut off = 0; + loop { + let count = fd.read(&mut buf)?; + if count == 0 { + break; + } + + line_print(off, &buf[..count]); + off += count; + } + + Ok(()) +} + +#[no_mangle] +fn main() -> i32 { + let args = libusr::env::args(); + let mut res = 0; + + if args.len() == 1 { + if let Err(e) = do_hexd(io::stdin()) { + eprintln!("{}: {:?}", ".", e); + res = -1; + } + } else { + for arg in &args[1..] { + if let Err(e) = File::open(arg).map(do_hexd) { + eprintln!("{}: {:?}", arg, e); + res = -1; + } + } + } + + res +}