Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend the FUSE support #480

Merged
merged 5 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
[workspace]
resolver = "2"
members = [
"hermit-abi",
"hermit",
"benches/alloc",
"benches/netbench",
"benches/micro",
"examples/tokio",
"benches/netbench",
"examples/demo",
"examples/fuse_test",
"examples/hello_world",
"examples/httpd",
"examples/demo",
"examples/testtcp",
"examples/testudp",
"examples/tokio",
"examples/webserver",
"hermit",
"hermit-abi",
]
exclude = ["target", "kernel"]
20 changes: 20 additions & 0 deletions examples/fuse_test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "fuse_test"
version = "0.1.0"
edition = "2021"
publish = false

[target.'cfg(target_os = "hermit")'.dependencies.hermit]
path = "../../hermit"
default-features = false

[features]
default = ["pci", "acpi", "fs"]
vga = ["hermit/vga"]
fs = ["hermit/fs"]
pci = ["hermit/pci"]
pci-ids = ["hermit/pci-ids"]
acpi = ["hermit/acpi"]
fsgsbase = ["hermit/fsgsbase"]
smp = ["hermit/smp"]
instrument = ["hermit/instrument"]
59 changes: 59 additions & 0 deletions examples/fuse_test/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#[cfg(target_os = "hermit")]
use hermit as _;

use std::{fs, path::Path};

#[cfg(target_os = "hermit")]
const TEST_DIR: &str = "/root";
#[cfg(not(target_os = "hermit"))]
const TEST_DIR: &str = "/tmp/data";

fn main() {
let test_path = Path::new(TEST_DIR);
assert!(test_path.is_dir());
let paths = fs::read_dir(test_path).unwrap();

let path_to_new_dir = test_path.join("new_dir");

assert!(!path_to_new_dir.exists());
fs::create_dir(&path_to_new_dir).unwrap();
assert!(path_to_new_dir.exists());

for direntry in paths {
let direntry = direntry.unwrap();
println!("\nPath: {}", direntry.path().display());
println!("Name: {}", direntry.file_name().into_string().unwrap());
let file_type = direntry.file_type().unwrap();
if file_type.is_dir() {
println!("Is dir!");
} else if file_type.is_file() {
println!("Is file!");
println!("Content: {}", fs::read_to_string(direntry.path()).unwrap());
let file = fs::File::open(direntry.path()).unwrap();
assert!(file.metadata().unwrap().is_file());
} else if file_type.is_symlink() {
println!("Is symlink!");
println!(
"Points to file: {:?}",
fs::metadata(direntry.path()).unwrap().file_type().is_file()
);
} else {
println!("Unknown type!");
}

let meta_data = direntry.metadata().unwrap();
assert!(meta_data.file_type() == file_type);

println!("Size: {} bytes", meta_data.len());
println!("Accessed: {:?}", meta_data.accessed().unwrap());
println!("Created: {:?}", meta_data.created().unwrap());
println!("Modified: {:?}", meta_data.modified().unwrap());
println!("Read only: {:?}", meta_data.permissions().readonly());
}

assert!(path_to_new_dir.exists());
fs::remove_dir(&path_to_new_dir).unwrap();
assert!(!path_to_new_dir.exists());

println!("Done.");
}
27 changes: 27 additions & 0 deletions examples/webserver/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
name = "webserver"
version = "0.1.0"
edition = "2021"

[dependencies]
ascii = "1"
time = "0.3"
tiny_http = "0.12"

[target.'cfg(target_os = "hermit")'.dependencies.hermit]
path = "../../hermit"
default-features = false

[features]
default = ["pci", "pci-ids", "fs", "acpi", "tcp"]
fs = ["hermit/fs"]
vga = ["hermit/vga"]
dhcpv4 = ["hermit/dhcpv4"]
pci = ["hermit/pci"]
pci-ids = ["hermit/pci-ids"]
acpi = ["hermit/acpi"]
fsgsbase = ["hermit/fsgsbase"]
smp = ["hermit/smp"]
tcp = ["hermit/tcp"]
instrument = ["hermit/instrument"]
trace = ["hermit/trace"]
75 changes: 75 additions & 0 deletions examples/webserver/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#[cfg(target_os = "hermit")]
use hermit as _;

use ascii::AsciiString;
use std::fs;
use std::path::Path;

extern crate ascii;
extern crate tiny_http;

#[cfg(target_os = "hermit")]
const ROOT_DIR: &str = "/root";
#[cfg(not(target_os = "hermit"))]
const ROOT_DIR: &str = "/tmp/data";

fn get_content_type(path: &Path) -> &'static str {
let extension = match path.extension() {
None => return "text/plain",
Some(e) => e,
};

match extension.to_str().unwrap() {
"gif" => "image/gif",
"jpg" => "image/jpeg",
"jpeg" => "image/jpeg",
"png" => "image/png",
"pdf" => "application/pdf",
"htm" => "text/html; charset=utf8",
"html" => "text/html; charset=utf8",
"txt" => "text/plain; charset=utf8",
"css" => "text/css; charset=utf8",
_ => "text/plain; charset=utf8",
}
}

fn main() {
let root_path = Path::new(ROOT_DIR);
assert!(root_path.is_dir());

#[cfg(not(target_os = "hermit"))]
let server = tiny_http::Server::http("0.0.0.0:9000").unwrap();

#[cfg(target_os = "hermit")]
let server = tiny_http::Server::http("0.0.0.0:8000").unwrap();

let port = server.server_addr().to_ip().unwrap().port();
println!("Now listening on port {}", port);

loop {
let rq = match server.recv() {
Ok(rq) => rq,
Err(_) => break,
};

println!("{:?}", rq);

let url = rq.url().to_string();
let path = root_path.join(Path::new(&url[1..]));
println!("Path: {}", path.display());

if let Ok(file) = fs::File::open(&path) {
let response = tiny_http::Response::from_file(file);

let response = response.with_header(tiny_http::Header {
field: "Content-Type".parse().unwrap(),
value: AsciiString::from_ascii(get_content_type(&path)).unwrap(),
});

let _ = rq.respond(response);
} else {
let rep = tiny_http::Response::new_empty(tiny_http::StatusCode(404));
let _ = rq.respond(rep);
}
}
}
2 changes: 1 addition & 1 deletion hermit-abi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hermit-abi"
version = "0.3.2"
version = "0.3.3"
authors = ["Stefan Lankes"]
license = "MIT OR Apache-2.0"
edition = "2021"
Expand Down
85 changes: 85 additions & 0 deletions hermit-abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,58 @@ pub struct pollfd {
pub revents: i16, /* events returned */
}

#[repr(C)]
pub struct dirent {
pub d_ino: u64,
pub d_off: u64,
pub d_namelen: u32,
pub d_type: u32,
pub d_name: [u8; 0],
}

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub enum DirectoryEntry {
Invalid(i32),
Valid(*const dirent),
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct stat {
pub st_dev: u64,
pub st_ino: u64,
pub st_nlink: u64,
pub st_mode: u32,
pub st_uid: u32,
pub st_gid: u32,
pub st_rdev: u64,
pub st_size: i64,
pub st_blksize: i64,
pub st_blocks: i64,
pub st_atime: i64,
pub st_atime_nsec: i64,
pub st_mtime: i64,
pub st_mtime_nsec: i64,
pub st_ctime: i64,
pub st_ctime_nsec: i64,
}

pub const DT_UNKNOWN: u32 = 0;
pub const DT_FIFO: u32 = 1;
pub const DT_CHR: u32 = 2;
pub const DT_DIR: u32 = 4;
pub const DT_BLK: u32 = 6;
pub const DT_REG: u32 = 8;
pub const DT_LNK: u32 = 10;
pub const DT_SOCK: u32 = 12;
pub const DT_WHT: u32 = 14;

pub const S_IFDIR: u32 = 16384;
pub const S_IFREG: u32 = 32768;
pub const S_IFLNK: u32 = 40960;
pub const S_IFMT: u32 = 61440;

// sysmbols, which are part of the library operating system
extern "C" {
/// If the value at address matches the expected value, park the current thread until it is either
Expand Down Expand Up @@ -409,10 +461,32 @@ extern "C" {
#[link_name = "sys_open"]
pub fn open(name: *const i8, flags: i32, mode: i32) -> i32;

/// open a directory
///
/// The opendir() system call opens the directory specified by `name`.
#[link_name = "sys_opendir"]
pub fn opendir(name: *const i8) -> i32;

/// delete the file it refers to `name`
#[link_name = "sys_unlink"]
pub fn unlink(name: *const i8) -> i32;

/// remove directory it refers to `name`
#[link_name = "sys_rmdir"]
pub fn rmdir(name: *const i8) -> i32;

/// stat
#[link_name = "sys_stat"]
pub fn stat(name: *const i8, stat: *mut stat) -> i32;

/// lstat
#[link_name = "sys_lstat"]
pub fn lstat(name: *const i8, stat: *mut stat) -> i32;

/// fstat
#[link_name = "sys_fstat"]
pub fn fstat(fd: i32, stat: *mut stat) -> i32;

/// determines the number of activated processors
#[link_name = "sys_get_processor_count"]
pub fn get_processor_count() -> usize;
Expand Down Expand Up @@ -485,6 +559,17 @@ extern "C" {
#[link_name = "sys_read"]
pub fn read(fd: i32, buf: *mut u8, len: usize) -> isize;

/// 'readdir' returns a pointer to a dirent structure
/// representing the next directory entry in the directory stream
/// pointed to by the file descriptor
#[link_name = "sys_readdir"]
pub fn readdir(fd: i32) -> DirectoryEntry;

/// 'mkdir' attempts to create a directory,
/// it returns 0 on success and -1 on error
#[link_name = "sys_mkdir"]
pub fn mkdir(name: *const i8, mode: u32) -> i32;

/// Fill `len` bytes in `buf` with cryptographically secure random data.
///
/// Returns either the number of bytes written to buf (a positive value) or
Expand Down