Use UTF-8 for all paths
This commit is contained in:
36
Cargo.lock
generated
36
Cargo.lock
generated
@@ -17,17 +17,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.2"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.66"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -35,7 +35,7 @@ name = "fdt"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/thomhuds/fdt.git#baca9b0070c281dc99521ee901efcb10e5f84218"
|
||||
dependencies = [
|
||||
"byteorder 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -49,19 +49,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kernel"
|
||||
version = "0.1.54"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fdt 0.1.0 (git+https://gitlab.redox-os.org/thomhuds/fdt.git)",
|
||||
"goblin 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linked_list_allocator 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"paste 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"raw-cpuid 8.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.2.4",
|
||||
"redox_syscall 0.2.7",
|
||||
"rmm 0.1.0",
|
||||
"rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -96,10 +96,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.13"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -135,7 +135,7 @@ version = "7.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -145,13 +145,13 @@ version = "8.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.4"
|
||||
version = "0.2.7"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -241,15 +241,15 @@ dependencies = [
|
||||
"checksum bit_field 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||
"checksum bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum byteorder 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
||||
"checksum cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
"checksum cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||
"checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
"checksum fdt 0.1.0 (git+https://gitlab.redox-os.org/thomhuds/fdt.git)" = "<none>"
|
||||
"checksum goblin 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884"
|
||||
"checksum linked_list_allocator 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "47de1a43fad0250ee197e9e124e5b5deab3d7b39d4428ae8a6d741ceb340c362"
|
||||
"checksum linked_list_allocator 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
|
||||
"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
|
||||
"checksum log 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
|
||||
"checksum log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
"checksum paste 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
|
||||
"checksum paste-impl 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
|
||||
"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "kernel"
|
||||
version = "0.1.54"
|
||||
version = "0.2.5"
|
||||
build = "build.rs"
|
||||
edition = "2018"
|
||||
|
||||
|
||||
2
rmm
2
rmm
Submodule rmm updated: 132d91d3aa...7fd1218465
@@ -1,7 +1,7 @@
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
collections::VecDeque,
|
||||
string::String,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
@@ -237,7 +237,7 @@ pub struct Context {
|
||||
/// The name of the context
|
||||
pub name: Arc<RwLock<Box<str>>>,
|
||||
/// The current working directory
|
||||
pub cwd: Arc<RwLock<Vec<u8>>>,
|
||||
pub cwd: Arc<RwLock<String>>,
|
||||
/// The open files in the scheme
|
||||
pub files: Arc<RwLock<Vec<Option<FileDescriptor>>>>,
|
||||
/// Signal actions
|
||||
@@ -293,7 +293,7 @@ impl Context {
|
||||
tls: None,
|
||||
grants: Arc::new(RwLock::new(UserGrants::default())),
|
||||
name: Arc::new(RwLock::new(String::new().into_boxed_str())),
|
||||
cwd: Arc::new(RwLock::new(Vec::new())),
|
||||
cwd: Arc::new(RwLock::new(String::new())),
|
||||
files: Arc::new(RwLock::new(Vec::new())),
|
||||
actions: Arc::new(RwLock::new(vec![(
|
||||
SigAction {
|
||||
@@ -313,35 +313,34 @@ impl Context {
|
||||
/// This function will turn "foo" into "scheme:/path/foo"
|
||||
/// "/foo" will turn into "scheme:/foo"
|
||||
/// "bar:/foo" will be used directly, as it is already absolute
|
||||
pub fn canonicalize(&self, path: &[u8]) -> Vec<u8> {
|
||||
let mut canon = if path.iter().position(|&b| b == b':').is_none() {
|
||||
pub fn canonicalize(&self, path: &str) -> String {
|
||||
let mut canon = if path.find(':').is_none() {
|
||||
let cwd = self.cwd.read();
|
||||
|
||||
let mut canon = if !path.starts_with(b"/") {
|
||||
let mut canon = if !path.starts_with('/') {
|
||||
let mut c = cwd.clone();
|
||||
if ! c.ends_with(b"/") {
|
||||
c.push(b'/');
|
||||
if ! c.ends_with('/') {
|
||||
c.push('/');
|
||||
}
|
||||
c
|
||||
} else {
|
||||
cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec()
|
||||
cwd[..cwd.find(':').map_or(1, |i| i + 1)].to_string()
|
||||
};
|
||||
|
||||
canon.extend_from_slice(&path);
|
||||
canon.push_str(&path);
|
||||
canon
|
||||
} else {
|
||||
path.to_vec()
|
||||
path.to_string()
|
||||
};
|
||||
|
||||
// NOTE: assumes the scheme does not include anything like "../" or "./"
|
||||
let mut result = {
|
||||
let parts = canon.split(|&c| c == b'/')
|
||||
.filter(|&part| part != b".")
|
||||
let parts = canon.split('/')
|
||||
.rev()
|
||||
.scan(0, |nskip, part| {
|
||||
if part == b"." {
|
||||
if part == "." {
|
||||
Some(None)
|
||||
} else if part == b".." {
|
||||
} else if part == ".." {
|
||||
*nskip += 1;
|
||||
Some(None)
|
||||
} else if *nskip > 0 {
|
||||
@@ -357,18 +356,17 @@ impl Context {
|
||||
parts
|
||||
.iter()
|
||||
.rev()
|
||||
.fold(Vec::new(), |mut vec, &part| {
|
||||
vec.extend_from_slice(part);
|
||||
vec.push(b'/');
|
||||
vec
|
||||
.fold(String::new(), |mut string, &part| {
|
||||
string.push_str(part);
|
||||
string.push('/');
|
||||
string
|
||||
})
|
||||
};
|
||||
result.pop(); // remove extra '/'
|
||||
|
||||
// replace with the root of the scheme if it's empty
|
||||
if result.is_empty() {
|
||||
let pos = canon.iter()
|
||||
.position(|&b| b == b':')
|
||||
let pos = canon.find(':')
|
||||
.map_or(canon.len(), |p| p + 1);
|
||||
canon.truncate(pos);
|
||||
canon
|
||||
|
||||
12
src/lib.rs
12
src/lib.rs
@@ -168,24 +168,24 @@ static mut INIT_ENV: &[u8] = &[];
|
||||
/// Initialize userspace by running the initfs:bin/init process
|
||||
/// This function will also set the CWD to initfs:bin and open debug: as stdio
|
||||
pub extern fn userspace_init() {
|
||||
let path = b"initfs:/bin/init";
|
||||
let path = "initfs:/bin/init";
|
||||
let env = unsafe { INIT_ENV };
|
||||
|
||||
if let Err(err) = syscall::chdir(b"initfs:") {
|
||||
if let Err(err) = syscall::chdir("initfs:") {
|
||||
info!("Failed to enter initfs ({}).", err);
|
||||
info!("Perhaps the kernel was compiled with an incorrect INITFS_FOLDER \
|
||||
environment variable value?");
|
||||
panic!("Unexpected error while trying to enter initfs:.");
|
||||
}
|
||||
|
||||
assert_eq!(syscall::open(b"debug:", syscall::flag::O_RDONLY).map(FileHandle::into), Ok(0));
|
||||
assert_eq!(syscall::open(b"debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(1));
|
||||
assert_eq!(syscall::open(b"debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(2));
|
||||
assert_eq!(syscall::open("debug:", syscall::flag::O_RDONLY).map(FileHandle::into), Ok(0));
|
||||
assert_eq!(syscall::open("debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(1));
|
||||
assert_eq!(syscall::open("debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(2));
|
||||
|
||||
let fd = syscall::open(path, syscall::flag::O_RDONLY).expect("failed to open init");
|
||||
|
||||
let mut args = Vec::new();
|
||||
args.push(path.to_vec().into_boxed_slice());
|
||||
args.push(path.as_bytes().to_vec().into_boxed_slice());
|
||||
|
||||
let mut vars = Vec::new();
|
||||
for var in env.split(|b| *b == b'\n') {
|
||||
|
||||
@@ -217,13 +217,12 @@ fn serialize_table_filename(
|
||||
}
|
||||
|
||||
impl Scheme for AcpiScheme {
|
||||
fn open(&self, path: &[u8], flags: usize, opener_uid: u32, _opener_gid: u32) -> Result<usize> {
|
||||
fn open(&self, path: &str, flags: usize, opener_uid: u32, _opener_gid: u32) -> Result<usize> {
|
||||
if opener_uid != 0 {
|
||||
return Err(Error::new(EACCES));
|
||||
}
|
||||
|
||||
let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
let path_str = path_str.trim_start_matches('/');
|
||||
let path_str = path.trim_start_matches('/');
|
||||
|
||||
// TODO: Use some kind of component iterator.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ impl DebugScheme {
|
||||
}
|
||||
|
||||
impl Scheme for DebugScheme {
|
||||
fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
if uid != 0 {
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::syscall::scheme::Scheme;
|
||||
pub struct EventScheme;
|
||||
|
||||
impl Scheme for EventScheme {
|
||||
fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let id = next_queue_id();
|
||||
queues_mut().insert(id, Arc::new(EventQueue::new(id)));
|
||||
|
||||
|
||||
@@ -41,9 +41,8 @@ impl InitFsScheme {
|
||||
}
|
||||
|
||||
impl Scheme for InitFsScheme {
|
||||
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_utf8 = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
let path_trimmed = path_utf8.trim_matches('/');
|
||||
fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_trimmed = path.trim_matches('/');
|
||||
|
||||
//Have to iterate to get the path without allocation
|
||||
for entry in self.files.iter() {
|
||||
|
||||
@@ -139,11 +139,10 @@ const fn vector_to_irq(vector: u8) -> u8 {
|
||||
}
|
||||
|
||||
impl Scheme for IrqScheme {
|
||||
fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
if uid != 0 { return Err(Error::new(EACCES)) }
|
||||
|
||||
let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
let path_str = path_str.trim_start_matches('/');
|
||||
let path_str = path.trim_start_matches('/');
|
||||
|
||||
let handle: Handle = if path_str.is_empty() {
|
||||
if flags & O_DIRECTORY == 0 && flags & O_STAT == 0 { return Err(Error::new(EISDIR)) }
|
||||
|
||||
@@ -23,10 +23,8 @@ impl ITimerScheme {
|
||||
}
|
||||
|
||||
impl Scheme for ITimerScheme {
|
||||
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
|
||||
let clock = path_str.parse::<usize>().or(Err(Error::new(ENOENT)))?;
|
||||
fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let clock = path.parse::<usize>().or(Err(Error::new(ENOENT)))?;
|
||||
|
||||
match clock {
|
||||
CLOCK_REALTIME => (),
|
||||
|
||||
@@ -52,7 +52,7 @@ impl DiskScheme {
|
||||
}
|
||||
|
||||
impl Scheme for DiskScheme {
|
||||
fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
self.handles.write().insert(id, Handle {
|
||||
path: b"0",
|
||||
|
||||
@@ -15,7 +15,7 @@ impl MemoryScheme {
|
||||
}
|
||||
}
|
||||
impl Scheme for MemoryScheme {
|
||||
fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
//! The kernel validates paths and file descriptors before they are passed to schemes,
|
||||
//! also stripping the scheme identifier of paths if necessary.
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
collections::BTreeMap,
|
||||
string::ToString,
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use core::sync::atomic::AtomicUsize;
|
||||
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
@@ -92,11 +95,11 @@ int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize);
|
||||
int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize);
|
||||
|
||||
pub struct SchemeIter<'a> {
|
||||
inner: Option<::alloc::collections::btree_map::Iter<'a, Box<[u8]>, SchemeId>>
|
||||
inner: Option<::alloc::collections::btree_map::Iter<'a, Box<str>, SchemeId>>
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SchemeIter<'a> {
|
||||
type Item = (&'a Box<[u8]>, &'a SchemeId);
|
||||
type Item = (&'a Box<str>, &'a SchemeId);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.as_mut().and_then(|iter| iter.next())
|
||||
@@ -106,7 +109,7 @@ impl<'a> Iterator for SchemeIter<'a> {
|
||||
/// Scheme list type
|
||||
pub struct SchemeList {
|
||||
map: BTreeMap<SchemeId, Arc<dyn Scheme + Send + Sync>>,
|
||||
names: BTreeMap<SchemeNamespace, BTreeMap<Box<[u8]>, SchemeId>>,
|
||||
names: BTreeMap<SchemeNamespace, BTreeMap<Box<str>, SchemeId>>,
|
||||
next_ns: usize,
|
||||
next_id: usize
|
||||
}
|
||||
@@ -133,7 +136,7 @@ impl SchemeList {
|
||||
|
||||
//TODO: Only memory: is in the null namespace right now. It should be removed when
|
||||
//anonymous mmap's are implemented
|
||||
self.insert(ns, Box::new(*b"memory"), |_| Arc::new(MemoryScheme::new())).unwrap();
|
||||
self.insert(ns, "memory", |_| Arc::new(MemoryScheme::new())).unwrap();
|
||||
}
|
||||
|
||||
/// Initialize a new namespace
|
||||
@@ -142,12 +145,12 @@ impl SchemeList {
|
||||
self.next_ns += 1;
|
||||
self.names.insert(ns, BTreeMap::new());
|
||||
|
||||
self.insert(ns, Box::new(*b""), |scheme_id| Arc::new(RootScheme::new(ns, scheme_id))).unwrap();
|
||||
self.insert(ns, Box::new(*b"event"), |_| Arc::new(EventScheme)).unwrap();
|
||||
self.insert(ns, Box::new(*b"itimer"), |_| Arc::new(ITimerScheme::new())).unwrap();
|
||||
self.insert(ns, Box::new(*b"memory"), |_| Arc::new(MemoryScheme::new())).unwrap();
|
||||
self.insert(ns, Box::new(*b"sys"), |_| Arc::new(SysScheme::new())).unwrap();
|
||||
self.insert(ns, Box::new(*b"time"), |scheme_id| Arc::new(TimeScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "", |scheme_id| Arc::new(RootScheme::new(ns, scheme_id))).unwrap();
|
||||
self.insert(ns, "event", |_| Arc::new(EventScheme)).unwrap();
|
||||
self.insert(ns, "itimer", |_| Arc::new(ITimerScheme::new())).unwrap();
|
||||
self.insert(ns, "memory", |_| Arc::new(MemoryScheme::new())).unwrap();
|
||||
self.insert(ns, "sys", |_| Arc::new(SysScheme::new())).unwrap();
|
||||
self.insert(ns, "time", |scheme_id| Arc::new(TimeScheme::new(scheme_id))).unwrap();
|
||||
|
||||
ns
|
||||
}
|
||||
@@ -159,23 +162,23 @@ impl SchemeList {
|
||||
|
||||
// These schemes should only be available on the root
|
||||
#[cfg(feature = "acpi")] {
|
||||
self.insert(ns, Box::new(*b"acpi"), |_| Arc::new(AcpiScheme::new())).unwrap();
|
||||
self.insert(ns, "acpi", |_| Arc::new(AcpiScheme::new())).unwrap();
|
||||
}
|
||||
self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(DebugScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(InitFsScheme::new())).unwrap();
|
||||
self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(IrqScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, Box::new(*b"proc"), |scheme_id| Arc::new(ProcScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, Box::new(*b"serio"), |scheme_id| Arc::new(SerioScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "debug", |scheme_id| Arc::new(DebugScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "initfs", |_| Arc::new(InitFsScheme::new())).unwrap();
|
||||
self.insert(ns, "irq", |scheme_id| Arc::new(IrqScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "proc", |scheme_id| Arc::new(ProcScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "serio", |scheme_id| Arc::new(SerioScheme::new(scheme_id))).unwrap();
|
||||
|
||||
#[cfg(feature = "live")] {
|
||||
self.insert(ns, Box::new(*b"disk/live"), |_| Arc::new(self::live::DiskScheme::new())).unwrap();
|
||||
self.insert(ns, "disk/live", |_| Arc::new(self::live::DiskScheme::new())).unwrap();
|
||||
}
|
||||
|
||||
// Pipe is special and needs to be in the root namespace
|
||||
self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(PipeScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "pipe", |scheme_id| Arc::new(PipeScheme::new(scheme_id))).unwrap();
|
||||
}
|
||||
|
||||
pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result<SchemeNamespace> {
|
||||
pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&str]) -> Result<SchemeNamespace> {
|
||||
// Create an empty namespace
|
||||
let to = self.new_ns();
|
||||
|
||||
@@ -188,7 +191,7 @@ impl SchemeList {
|
||||
};
|
||||
|
||||
if let Some(ref mut names) = self.names.get_mut(&to) {
|
||||
assert!(names.insert(name.to_vec().into_boxed_slice(), id).is_none());
|
||||
assert!(names.insert(name.to_string().into_boxed_str(), id).is_none());
|
||||
} else {
|
||||
panic!("scheme namespace not found");
|
||||
}
|
||||
@@ -212,7 +215,7 @@ impl SchemeList {
|
||||
self.map.get(&id)
|
||||
}
|
||||
|
||||
pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<dyn Scheme + Send + Sync>)> {
|
||||
pub fn get_name(&self, ns: SchemeNamespace, name: &str) -> Option<(SchemeId, &Arc<dyn Scheme + Send + Sync>)> {
|
||||
if let Some(names) = self.names.get(&ns) {
|
||||
if let Some(&id) = names.get(name) {
|
||||
return self.get(id).map(|scheme| (id, scheme));
|
||||
@@ -222,11 +225,11 @@ impl SchemeList {
|
||||
}
|
||||
|
||||
/// Create a new scheme.
|
||||
pub fn insert<F>(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result<SchemeId>
|
||||
pub fn insert<F>(&mut self, ns: SchemeNamespace, name: &str, scheme_fn: F) -> Result<SchemeId>
|
||||
where F: Fn(SchemeId) -> Arc<dyn Scheme + Send + Sync>
|
||||
{
|
||||
if let Some(names) = self.names.get(&ns) {
|
||||
if names.contains_key(&name) {
|
||||
if names.contains_key(name) {
|
||||
return Err(Error::new(EEXIST));
|
||||
}
|
||||
}
|
||||
@@ -252,7 +255,7 @@ impl SchemeList {
|
||||
|
||||
assert!(self.map.insert(id, scheme).is_none());
|
||||
if let Some(ref mut names) = self.names.get_mut(&ns) {
|
||||
assert!(names.insert(name, id).is_none());
|
||||
assert!(names.insert(name.to_string().into_boxed_str(), id).is_none());
|
||||
} else {
|
||||
// Nonexistent namespace, posssibly null namespace
|
||||
return Err(Error::new(ENODEV));
|
||||
|
||||
@@ -24,6 +24,7 @@ use core::{
|
||||
cmp,
|
||||
mem,
|
||||
slice,
|
||||
str,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
use spin::RwLock;
|
||||
@@ -208,8 +209,7 @@ impl ProcScheme {
|
||||
}
|
||||
|
||||
impl Scheme for ProcScheme {
|
||||
fn open(&self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result<usize> {
|
||||
let path = core::str::from_utf8(path).map_err(|_| Error::new(EINVAL))?;
|
||||
fn open(&self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<usize> {
|
||||
let mut parts = path.splitn(2, '/');
|
||||
let pid = parts.next()
|
||||
.and_then(|s| s.parse().ok())
|
||||
@@ -310,8 +310,10 @@ impl Scheme for ProcScheme {
|
||||
handle.info
|
||||
};
|
||||
|
||||
let mut path = format!("{}/", info.pid.into()).into_bytes();
|
||||
path.extend_from_slice(buf);
|
||||
let buf_str = str::from_utf8(buf).map_err(|_| Error::new(EINVAL))?;
|
||||
|
||||
let mut path = format!("{}/", info.pid.into());
|
||||
path.push_str(buf_str);
|
||||
|
||||
let (uid, gid) = {
|
||||
let contexts = context::contexts();
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use alloc::sync::Arc;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
collections::BTreeMap,
|
||||
string::ToString,
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use core::str;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use spin::{Mutex, RwLock};
|
||||
@@ -67,9 +70,8 @@ impl RootScheme {
|
||||
}
|
||||
|
||||
impl Scheme for RootScheme {
|
||||
fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_utf8 = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
let path_trimmed = path_utf8.trim_matches('/');
|
||||
fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path = path.trim_matches('/');
|
||||
|
||||
//TODO: Make this follow standards for flags and errors
|
||||
if flags & O_CREAT == O_CREAT {
|
||||
@@ -83,10 +85,10 @@ impl Scheme for RootScheme {
|
||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
let inner = {
|
||||
let path_box = path_trimmed.as_bytes().to_vec().into_boxed_slice();
|
||||
let path_box = path.to_string().into_boxed_str();
|
||||
let mut schemes = scheme::schemes_mut();
|
||||
let inner = Arc::new(UserInner::new(self.scheme_id, id, path_box.clone(), flags, context));
|
||||
schemes.insert(self.scheme_ns, path_box, |scheme_id| {
|
||||
let inner = Arc::new(UserInner::new(self.scheme_id, id, path_box, flags, context));
|
||||
schemes.insert(self.scheme_ns, path, |scheme_id| {
|
||||
inner.scheme_id.store(scheme_id, Ordering::SeqCst);
|
||||
Arc::new(UserScheme::new(Arc::downgrade(&inner)))
|
||||
})?;
|
||||
@@ -99,7 +101,7 @@ impl Scheme for RootScheme {
|
||||
} else {
|
||||
Err(Error::new(EACCES))
|
||||
}
|
||||
} else if path_trimmed.is_empty() {
|
||||
} else if path.is_empty() {
|
||||
let scheme_ns = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -111,7 +113,7 @@ impl Scheme for RootScheme {
|
||||
{
|
||||
let schemes = scheme::schemes();
|
||||
for (name, _scheme_id) in schemes.iter_name(scheme_ns) {
|
||||
data.extend_from_slice(name);
|
||||
data.extend_from_slice(name.as_bytes());
|
||||
data.push(b'\n');
|
||||
}
|
||||
}
|
||||
@@ -126,7 +128,7 @@ impl Scheme for RootScheme {
|
||||
Ok(id)
|
||||
} else {
|
||||
let inner = Arc::new(
|
||||
path_trimmed.as_bytes().to_vec().into_boxed_slice()
|
||||
path.as_bytes().to_vec().into_boxed_slice()
|
||||
);
|
||||
|
||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
@@ -135,9 +137,8 @@ impl Scheme for RootScheme {
|
||||
}
|
||||
}
|
||||
|
||||
fn unlink(&self, path: &[u8], uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_utf8 = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
let path_trimmed = path_utf8.trim_matches('/');
|
||||
fn unlink(&self, path: &str, uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path = path.trim_matches('/');
|
||||
|
||||
if uid == 0 {
|
||||
let inner = {
|
||||
@@ -145,7 +146,7 @@ impl Scheme for RootScheme {
|
||||
handles.iter().find_map(|(_id, handle)| {
|
||||
match handle {
|
||||
Handle::Scheme(inner) => {
|
||||
if path_trimmed.as_bytes() == inner.name.as_ref() {
|
||||
if path == inner.name.as_ref() {
|
||||
return Some(inner.clone());
|
||||
}
|
||||
},
|
||||
@@ -257,9 +258,10 @@ impl Scheme for RootScheme {
|
||||
|
||||
match handle {
|
||||
Handle::Scheme(inner) => {
|
||||
let name = inner.name.as_bytes();
|
||||
let mut j = 0;
|
||||
while i < buf.len() && j < inner.name.len() {
|
||||
buf[i] = inner.name[j];
|
||||
while i < buf.len() && j < name.len() {
|
||||
buf[i] = name[j];
|
||||
i += 1;
|
||||
j += 1;
|
||||
}
|
||||
|
||||
@@ -60,13 +60,12 @@ impl SerioScheme {
|
||||
}
|
||||
|
||||
impl Scheme for SerioScheme {
|
||||
fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
if uid != 0 {
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
|
||||
let index = str::from_utf8(path)
|
||||
.or(Err(Error::new(ENOENT)))?
|
||||
let index = path
|
||||
.parse::<usize>()
|
||||
.or(Err(Error::new(ENOENT)))?;
|
||||
if index >= INPUT.len() {
|
||||
|
||||
@@ -23,7 +23,7 @@ mod syscall;
|
||||
mod uname;
|
||||
|
||||
struct Handle {
|
||||
path: &'static [u8],
|
||||
path: &'static str,
|
||||
data: Vec<u8>,
|
||||
mode: u16,
|
||||
seek: usize
|
||||
@@ -34,26 +34,26 @@ type SysFn = dyn Fn() -> Result<Vec<u8>> + Send + Sync;
|
||||
/// System information scheme
|
||||
pub struct SysScheme {
|
||||
next_id: AtomicUsize,
|
||||
files: BTreeMap<&'static [u8], Box<SysFn>>,
|
||||
files: BTreeMap<&'static str, Box<SysFn>>,
|
||||
handles: RwLock<BTreeMap<usize, Handle>>
|
||||
}
|
||||
|
||||
impl SysScheme {
|
||||
pub fn new() -> SysScheme {
|
||||
let mut files: BTreeMap<&'static [u8], Box<SysFn>> = BTreeMap::new();
|
||||
let mut files: BTreeMap<&'static str, Box<SysFn>> = BTreeMap::new();
|
||||
|
||||
files.insert(b"block", Box::new(block::resource));
|
||||
files.insert(b"context", Box::new(context::resource));
|
||||
files.insert(b"cpu", Box::new(cpu::resource));
|
||||
files.insert(b"exe", Box::new(exe::resource));
|
||||
files.insert(b"iostat", Box::new(iostat::resource));
|
||||
files.insert(b"log", Box::new(log::resource));
|
||||
files.insert(b"scheme", Box::new(scheme::resource));
|
||||
files.insert(b"scheme_num", Box::new(scheme_num::resource));
|
||||
files.insert(b"syscall", Box::new(syscall::resource));
|
||||
files.insert(b"uname", Box::new(uname::resource));
|
||||
files.insert("block", Box::new(block::resource));
|
||||
files.insert("context", Box::new(context::resource));
|
||||
files.insert("cpu", Box::new(cpu::resource));
|
||||
files.insert("exe", Box::new(exe::resource));
|
||||
files.insert("iostat", Box::new(iostat::resource));
|
||||
files.insert("log", Box::new(log::resource));
|
||||
files.insert("scheme", Box::new(scheme::resource));
|
||||
files.insert("scheme_num", Box::new(scheme_num::resource));
|
||||
files.insert("syscall", Box::new(syscall::resource));
|
||||
files.insert("uname", Box::new(uname::resource));
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
files.insert(b"spurious_irq", Box::new(irq::spurious_irq_resource));
|
||||
files.insert("spurious_irq", Box::new(irq::spurious_irq_resource));
|
||||
|
||||
SysScheme {
|
||||
next_id: AtomicUsize::new(0),
|
||||
@@ -64,22 +64,21 @@ impl SysScheme {
|
||||
}
|
||||
|
||||
impl Scheme for SysScheme {
|
||||
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_utf8 = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
let path_trimmed = path_utf8.trim_matches('/');
|
||||
fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path = path.trim_matches('/');
|
||||
|
||||
if path_trimmed.is_empty() {
|
||||
if path.is_empty() {
|
||||
let mut data = Vec::new();
|
||||
for entry in self.files.iter() {
|
||||
if ! data.is_empty() {
|
||||
data.push(b'\n');
|
||||
}
|
||||
data.extend_from_slice(entry.0);
|
||||
data.extend_from_slice(entry.0.as_bytes());
|
||||
}
|
||||
|
||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
self.handles.write().insert(id, Handle {
|
||||
path: b"",
|
||||
path: "",
|
||||
data,
|
||||
mode: MODE_DIR | 0o444,
|
||||
seek: 0
|
||||
@@ -88,7 +87,7 @@ impl Scheme for SysScheme {
|
||||
} else {
|
||||
//Have to iterate to get the path without allocation
|
||||
for entry in self.files.iter() {
|
||||
if entry.0 == &path_trimmed.as_bytes() {
|
||||
if entry.0 == &path {
|
||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
let data = entry.1()?;
|
||||
self.handles.write().insert(id, Handle {
|
||||
@@ -139,9 +138,10 @@ impl Scheme for SysScheme {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let path = handle.path.as_bytes();
|
||||
let mut j = 0;
|
||||
while i < buf.len() && j < handle.path.len() {
|
||||
buf[i] = handle.path[j];
|
||||
while i < buf.len() && j < path.len() {
|
||||
buf[i] = path[j];
|
||||
i += 1;
|
||||
j += 1;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
|
||||
let schemes = scheme::schemes();
|
||||
for (name, _scheme_id) in schemes.iter_name(scheme_ns) {
|
||||
data.extend_from_slice(name);
|
||||
data.extend_from_slice(name.as_bytes());
|
||||
data.push(b'\n');
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
let schemes = scheme::schemes();
|
||||
for (name, &scheme_id) in schemes.iter_name(scheme_ns) {
|
||||
data.extend_from_slice(format!("{:>4}: ", scheme_id.into()).as_bytes());
|
||||
data.extend_from_slice(name);
|
||||
data.extend_from_slice(name.as_bytes());
|
||||
data.push(b'\n');
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,8 @@ impl TimeScheme {
|
||||
}
|
||||
|
||||
impl Scheme for TimeScheme {
|
||||
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
|
||||
let clock = path_str.parse::<usize>().or(Err(Error::new(ENOENT)))?;
|
||||
fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let clock = path.parse::<usize>().or(Err(Error::new(ENOENT)))?;
|
||||
|
||||
match clock {
|
||||
CLOCK_REALTIME => (),
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::syscall::scheme::Scheme;
|
||||
pub struct UserInner {
|
||||
root_id: SchemeId,
|
||||
handle_id: usize,
|
||||
pub name: Box<[u8]>,
|
||||
pub name: Box<str>,
|
||||
pub flags: usize,
|
||||
pub scheme_id: AtomicSchemeId,
|
||||
next_id: AtomicU64,
|
||||
@@ -36,7 +36,7 @@ pub struct UserInner {
|
||||
}
|
||||
|
||||
impl UserInner {
|
||||
pub fn new(root_id: SchemeId, handle_id: usize, name: Box<[u8]>, flags: usize, context: Weak<RwLock<Context>>) -> UserInner {
|
||||
pub fn new(root_id: SchemeId, handle_id: usize, name: Box<str>, flags: usize, context: Weak<RwLock<Context>>) -> UserInner {
|
||||
UserInner {
|
||||
root_id,
|
||||
handle_id,
|
||||
@@ -103,13 +103,27 @@ impl UserInner {
|
||||
/// Map a readable structure to the scheme's userspace and return the
|
||||
/// pointer
|
||||
pub fn capture(&self, buf: &[u8]) -> Result<usize> {
|
||||
UserInner::capture_inner(&self.context, 0, buf.as_ptr() as usize, buf.len(), PROT_READ, None).map(|addr| addr.data())
|
||||
UserInner::capture_inner(
|
||||
&self.context,
|
||||
0,
|
||||
buf.as_ptr() as usize,
|
||||
buf.len(),
|
||||
PROT_READ,
|
||||
None
|
||||
).map(|addr| addr.data())
|
||||
}
|
||||
|
||||
/// Map a writeable structure to the scheme's userspace and return the
|
||||
/// pointer
|
||||
pub fn capture_mut(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
UserInner::capture_inner(&self.context, 0, buf.as_mut_ptr() as usize, buf.len(), PROT_WRITE, None).map(|addr| addr.data())
|
||||
UserInner::capture_inner(
|
||||
&self.context,
|
||||
0,
|
||||
buf.as_mut_ptr() as usize,
|
||||
buf.len(),
|
||||
PROT_WRITE,
|
||||
None
|
||||
).map(|addr| addr.data())
|
||||
}
|
||||
|
||||
fn capture_inner(context_weak: &Weak<RwLock<Context>>, to_address: usize, address: usize, size: usize, flags: MapFlags, desc_opt: Option<FileDescriptor>)
|
||||
@@ -257,33 +271,33 @@ impl UserScheme {
|
||||
}
|
||||
|
||||
impl Scheme for UserScheme {
|
||||
fn open(&self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn open(&self, path: &str, flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let address = inner.capture(path.as_bytes())?;
|
||||
let result = inner.call(SYS_OPEN, address, path.len(), flags);
|
||||
let _ = inner.release(address);
|
||||
result
|
||||
}
|
||||
|
||||
fn chmod(&self, path: &[u8], mode: u16, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn chmod(&self, path: &str, mode: u16, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let address = inner.capture(path.as_bytes())?;
|
||||
let result = inner.call(SYS_CHMOD, address, path.len(), mode as usize);
|
||||
let _ = inner.release(address);
|
||||
result
|
||||
}
|
||||
|
||||
fn rmdir(&self, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn rmdir(&self, path: &str, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let address = inner.capture(path.as_bytes())?;
|
||||
let result = inner.call(SYS_RMDIR, address, path.len(), 0);
|
||||
let _ = inner.release(address);
|
||||
result
|
||||
}
|
||||
|
||||
fn unlink(&self, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn unlink(&self, path: &str, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let address = inner.capture(path.as_bytes())?;
|
||||
let result = inner.call(SYS_UNLINK, address, path.len(), 0);
|
||||
let _ = inner.release(address);
|
||||
result
|
||||
@@ -513,9 +527,9 @@ impl Scheme for UserScheme {
|
||||
result
|
||||
}
|
||||
|
||||
fn frename(&self, file: usize, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
|
||||
fn frename(&self, file: usize, path: &str, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let address = inner.capture(path.as_bytes())?;
|
||||
let result = inner.call(SYS_FRENAME, file, address, path.len());
|
||||
let _ = inner.release(address);
|
||||
result
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Filesystem syscalls
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use core::str;
|
||||
use core::sync::atomic::Ordering;
|
||||
use spin::RwLock;
|
||||
|
||||
@@ -55,7 +56,7 @@ pub fn file_op_mut_slice(a: usize, fd: FileHandle, slice: &mut [u8]) -> Result<u
|
||||
}
|
||||
|
||||
/// Change the current working directory
|
||||
pub fn chdir(path: &[u8]) -> Result<usize> {
|
||||
pub fn chdir(path: &str) -> Result<usize> {
|
||||
let fd = open(path, O_RDONLY | O_DIRECTORY)?;
|
||||
let mut stat = Stat::default();
|
||||
let stat_res = file_op_mut_slice(syscall::number::SYS_FSTAT, fd, &mut stat);
|
||||
@@ -79,16 +80,17 @@ pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
let cwd = context.cwd.read();
|
||||
let cwd_bytes = cwd.as_bytes();
|
||||
let mut i = 0;
|
||||
while i < buf.len() && i < cwd.len() {
|
||||
buf[i] = cwd[i];
|
||||
while i < buf.len() && i < cwd_bytes.len() {
|
||||
buf[i] = cwd_bytes[i];
|
||||
i += 1;
|
||||
}
|
||||
Ok(i)
|
||||
}
|
||||
|
||||
/// Open syscall
|
||||
pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
|
||||
pub fn open(path: &str, flags: usize) -> Result<FileHandle> {
|
||||
let (mut path_canon, uid, gid, scheme_ns, umask) = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -103,7 +105,7 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
|
||||
for _level in 0..32 { // XXX What should the limit be?
|
||||
//println!(" level {} = {:?}", _level, ::core::str::from_utf8(&path_canon));
|
||||
|
||||
let mut parts = path_canon.splitn(2, |&b| b == b':');
|
||||
let mut parts = path_canon.splitn(2, ':');
|
||||
let scheme_name_opt = parts.next();
|
||||
let reference_opt = parts.next();
|
||||
|
||||
@@ -114,7 +116,7 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
|
||||
let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
(scheme_id, Arc::clone(&scheme))
|
||||
};
|
||||
let reference = reference_opt.unwrap_or(b"");
|
||||
let reference = reference_opt.unwrap_or("");
|
||||
let file_id = match scheme.open(reference, flags, uid, gid) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => if err.errno == EXDEV {
|
||||
@@ -128,10 +130,12 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
|
||||
|
||||
let count = res?;
|
||||
|
||||
let buf_str = str::from_utf8(&buf[..count]).map_err(|_| Error::new(EINVAL))?;
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
path_canon = context.canonicalize(&buf[..count]);
|
||||
path_canon = context.canonicalize(buf_str);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
@@ -196,7 +200,7 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result<usize> {
|
||||
}
|
||||
|
||||
/// chmod syscall
|
||||
pub fn chmod(path: &[u8], mode: u16) -> Result<usize> {
|
||||
pub fn chmod(path: &str, mode: u16) -> Result<usize> {
|
||||
let (path_canon, uid, gid, scheme_ns) = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -204,7 +208,7 @@ pub fn chmod(path: &[u8], mode: u16) -> Result<usize> {
|
||||
(context.canonicalize(path), context.euid, context.egid, context.ens)
|
||||
};
|
||||
|
||||
let mut parts = path_canon.splitn(2, |&b| b == b':');
|
||||
let mut parts = path_canon.splitn(2, ':');
|
||||
let scheme_name_opt = parts.next();
|
||||
let reference_opt = parts.next();
|
||||
|
||||
@@ -214,11 +218,11 @@ pub fn chmod(path: &[u8], mode: u16) -> Result<usize> {
|
||||
let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
Arc::clone(&scheme)
|
||||
};
|
||||
scheme.chmod(reference_opt.unwrap_or(b""), mode, uid, gid)
|
||||
scheme.chmod(reference_opt.unwrap_or(""), mode, uid, gid)
|
||||
}
|
||||
|
||||
/// rmdir syscall
|
||||
pub fn rmdir(path: &[u8]) -> Result<usize> {
|
||||
pub fn rmdir(path: &str) -> Result<usize> {
|
||||
let (path_canon, uid, gid, scheme_ns) = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -226,7 +230,7 @@ pub fn rmdir(path: &[u8]) -> Result<usize> {
|
||||
(context.canonicalize(path), context.euid, context.egid, context.ens)
|
||||
};
|
||||
|
||||
let mut parts = path_canon.splitn(2, |&b| b == b':');
|
||||
let mut parts = path_canon.splitn(2, ':');
|
||||
let scheme_name_opt = parts.next();
|
||||
let reference_opt = parts.next();
|
||||
|
||||
@@ -236,11 +240,11 @@ pub fn rmdir(path: &[u8]) -> Result<usize> {
|
||||
let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
Arc::clone(&scheme)
|
||||
};
|
||||
scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid)
|
||||
scheme.rmdir(reference_opt.unwrap_or(""), uid, gid)
|
||||
}
|
||||
|
||||
/// Unlink syscall
|
||||
pub fn unlink(path: &[u8]) -> Result<usize> {
|
||||
pub fn unlink(path: &str) -> Result<usize> {
|
||||
let (path_canon, uid, gid, scheme_ns) = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -248,7 +252,7 @@ pub fn unlink(path: &[u8]) -> Result<usize> {
|
||||
(context.canonicalize(path), context.euid, context.egid, context.ens)
|
||||
};
|
||||
|
||||
let mut parts = path_canon.splitn(2, |&b| b == b':');
|
||||
let mut parts = path_canon.splitn(2, ':');
|
||||
let scheme_name_opt = parts.next();
|
||||
let reference_opt = parts.next();
|
||||
|
||||
@@ -258,7 +262,7 @@ pub fn unlink(path: &[u8]) -> Result<usize> {
|
||||
let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
Arc::clone(&scheme)
|
||||
};
|
||||
scheme.unlink(reference_opt.unwrap_or(b""), uid, gid)
|
||||
scheme.unlink(reference_opt.unwrap_or(""), uid, gid)
|
||||
}
|
||||
|
||||
/// Close syscall
|
||||
@@ -409,7 +413,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn frename(fd: FileHandle, path: &[u8]) -> Result<usize> {
|
||||
pub fn frename(fd: FileHandle, path: &str) -> Result<usize> {
|
||||
let file = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -424,7 +428,7 @@ pub fn frename(fd: FileHandle, path: &[u8]) -> Result<usize> {
|
||||
(context.canonicalize(path), context.euid, context.egid, context.ens)
|
||||
};
|
||||
|
||||
let mut parts = path_canon.splitn(2, |&b| b == b':');
|
||||
let mut parts = path_canon.splitn(2, ':');
|
||||
let scheme_name_opt = parts.next();
|
||||
let reference_opt = parts.next();
|
||||
|
||||
@@ -438,7 +442,7 @@ pub fn frename(fd: FileHandle, path: &[u8]) -> Result<usize> {
|
||||
let description = file.description.read();
|
||||
|
||||
if scheme_id == description.scheme {
|
||||
scheme.frename(description.number, reference_opt.unwrap_or(b""), uid, gid)
|
||||
scheme.frename(description.number, reference_opt.unwrap_or(""), uid, gid)
|
||||
} else {
|
||||
Err(Error::new(EXDEV))
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
SYS_DUP2 => dup2(fd, FileHandle::from(c), validate_slice(d as *const u8, e)?).map(FileHandle::into),
|
||||
SYS_FCNTL => fcntl(fd, c, d),
|
||||
SYS_FEXEC => fexec(fd, validate_slice(c as *const [usize; 2], d)?, validate_slice(e as *const [usize; 2], f)?),
|
||||
SYS_FRENAME => frename(fd, validate_slice(c as *const u8, d)?),
|
||||
SYS_FRENAME => frename(fd, validate_str(c as *const u8, d)?),
|
||||
SYS_FUNMAP => funmap(b, c),
|
||||
SYS_FMAP_OLD => {
|
||||
{
|
||||
@@ -100,10 +100,10 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
}
|
||||
},
|
||||
SYS_CLASS_PATH => match a {
|
||||
SYS_OPEN => open(validate_slice(b as *const u8, c)?, d).map(FileHandle::into),
|
||||
SYS_CHMOD => chmod(validate_slice(b as *const u8, c)?, d as u16),
|
||||
SYS_RMDIR => rmdir(validate_slice(b as *const u8, c)?),
|
||||
SYS_UNLINK => unlink(validate_slice(b as *const u8, c)?),
|
||||
SYS_OPEN => open(validate_str(b as *const u8, c)?, d).map(FileHandle::into),
|
||||
SYS_CHMOD => chmod(validate_str(b as *const u8, c)?, d as u16),
|
||||
SYS_RMDIR => rmdir(validate_str(b as *const u8, c)?),
|
||||
SYS_UNLINK => unlink(validate_str(b as *const u8, c)?),
|
||||
_ => Err(Error::new(ENOSYS))
|
||||
},
|
||||
_ => match a {
|
||||
@@ -145,7 +145,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
SYS_EXIT => exit((b & 0xFF) << 8),
|
||||
SYS_KILL => kill(ContextId::from(b), c),
|
||||
SYS_WAITPID => waitpid(ContextId::from(b), c, WaitFlags::from_bits_truncate(d)).map(ContextId::into),
|
||||
SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?),
|
||||
SYS_CHDIR => chdir(validate_str(b as *const u8, c)?),
|
||||
SYS_IOPL => iopl(b, stack),
|
||||
SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),
|
||||
SYS_GETEGID => getegid(),
|
||||
|
||||
@@ -3,7 +3,7 @@ use alloc::vec::Vec;
|
||||
use crate::context;
|
||||
use crate::scheme::{self, SchemeNamespace};
|
||||
use crate::syscall::error::*;
|
||||
use crate::syscall::validate::validate_slice;
|
||||
use crate::syscall::validate::validate_str;
|
||||
|
||||
pub fn getegid() -> Result<usize> {
|
||||
let contexts = context::contexts();
|
||||
@@ -50,7 +50,7 @@ pub fn getuid() -> Result<usize> {
|
||||
pub fn mkns(name_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||
let mut names = Vec::new();
|
||||
for name_ptr in name_ptrs {
|
||||
names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?);
|
||||
names.push(validate_str(name_ptr[0] as *const u8, name_ptr[1])?);
|
||||
}
|
||||
|
||||
let (uid, from) = {
|
||||
|
||||
@@ -7,7 +7,7 @@ use alloc::{
|
||||
};
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
use core::ops::DerefMut;
|
||||
use core::{intrinsics, mem};
|
||||
use core::{intrinsics, mem, str};
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::context::file::FileDescriptor;
|
||||
@@ -1030,9 +1030,11 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>
|
||||
}
|
||||
interp.truncate(i);
|
||||
|
||||
println!(" interpreter: {:?}", ::core::str::from_utf8(&interp));
|
||||
let interp_str = str::from_utf8(&interp).map_err(|_| Error::new(EINVAL))?;
|
||||
|
||||
let interp_fd = super::fs::open(&interp, super::flag::O_RDONLY | super::flag::O_CLOEXEC)?;
|
||||
println!(" interpreter: {}", interp_str);
|
||||
|
||||
let interp_fd = super::fs::open(interp_str, super::flag::O_RDONLY | super::flag::O_CLOEXEC)?;
|
||||
|
||||
let mut args_vec = Vec::from(args);
|
||||
//TODO: pass file handle in auxv
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use core::{mem, slice};
|
||||
use core::{mem, slice, str};
|
||||
|
||||
use crate::paging::{ActivePageTable, PageTableType, Page, VirtualAddress, VirtualAddressType};
|
||||
use crate::paging::entry::EntryFlags;
|
||||
@@ -51,3 +51,10 @@ pub fn validate_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]
|
||||
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a pointer and length to str, if valid
|
||||
//TODO: Mark unsafe
|
||||
pub fn validate_str(ptr: *const u8, len: usize) -> Result<&'static str> {
|
||||
let slice = validate_slice(ptr, len)?;
|
||||
str::from_utf8(slice).map_err(|_| Error::new(EINVAL))
|
||||
}
|
||||
|
||||
2
syscall
2
syscall
Submodule syscall updated: bfdd0bb8d6...87e913d991
Reference in New Issue
Block a user