Use UTF-8 for all paths

This commit is contained in:
Jeremy Soller
2021-02-14 13:45:03 -07:00
parent 8fcd375bd9
commit d331f72f2a
28 changed files with 217 additions and 193 deletions

36
Cargo.lock generated
View File

@@ -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"

View File

@@ -1,6 +1,6 @@
[package]
name = "kernel"
version = "0.1.54"
version = "0.2.5"
build = "build.rs"
edition = "2018"

2
rmm

Submodule rmm updated: 132d91d3aa...7fd1218465

View File

@@ -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

View File

@@ -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') {

View File

@@ -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.

View File

@@ -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));
}

View File

@@ -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)));

View File

@@ -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() {

View File

@@ -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)) }

View File

@@ -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 => (),

View File

@@ -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",

View File

@@ -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)
}

View File

@@ -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));

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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() {

View File

@@ -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;
}

View File

@@ -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');
}

View File

@@ -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');
}

View File

@@ -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 => (),

View File

@@ -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

View File

@@ -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))
}

View File

@@ -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(),

View File

@@ -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) = {

View File

@@ -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

View File

@@ -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))
}

Submodule syscall updated: bfdd0bb8d6...87e913d991