From 94ef9dd14ac83f4427d5c07816b690755085afcb Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 23 Sep 2016 11:01:53 -0600 Subject: [PATCH] Add env --- kernel/context/context.rs | 5 +- kernel/scheme/env.rs | 148 +++++++++++++++++++++++++++---------- kernel/syscall/fs.rs | 18 +++++ kernel/syscall/mod.rs | 1 + kernel/syscall/process.rs | 9 +++ libstd | 2 +- programs/login/src/main.rs | 7 ++ 7 files changed, 151 insertions(+), 39 deletions(-) diff --git a/kernel/context/context.rs b/kernel/context/context.rs index 9dcc10b..504b5e4 100644 --- a/kernel/context/context.rs +++ b/kernel/context/context.rs @@ -1,6 +1,6 @@ use alloc::arc::Arc; use alloc::boxed::Box; -use collections::Vec; +use collections::{BTreeMap, Vec}; use spin::Mutex; use arch; @@ -39,6 +39,8 @@ pub struct Context { pub grants: Arc>>, /// The current working directory pub cwd: Arc>>, + /// The process environment + pub env: Arc, Arc>>>>>, /// The open files in the scheme pub files: Arc>>> } @@ -58,6 +60,7 @@ impl Context { stack: None, grants: Arc::new(Mutex::new(Vec::new())), cwd: Arc::new(Mutex::new(Vec::new())), + env: Arc::new(Mutex::new(BTreeMap::new())), files: Arc::new(Mutex::new(Vec::new())) } } diff --git a/kernel/scheme/env.rs b/kernel/scheme/env.rs index d1f494f..7f2bcb8 100644 --- a/kernel/scheme/env.rs +++ b/kernel/scheme/env.rs @@ -1,39 +1,31 @@ -use collections::BTreeMap; +use alloc::arc::Arc; +use collections::{BTreeMap, Vec}; use core::{cmp, str}; use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::RwLock; +use spin::{Mutex, RwLock}; +use context; use syscall::data::Stat; use syscall::error::*; -use syscall::flag::{MODE_DIR, MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END}; +use syscall::flag::{MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END}; use syscall::scheme::Scheme; +#[derive(Clone)] struct Handle { - data: &'static [u8], + data: Arc>>, mode: u16, seek: usize } pub struct EnvScheme { next_id: AtomicUsize, - files: BTreeMap<&'static [u8], &'static [u8]>, handles: RwLock> } impl EnvScheme { pub fn new() -> EnvScheme { - let mut files: BTreeMap<&'static [u8], &'static [u8]> = BTreeMap::new(); - - files.insert(b"", b"COLUMNS\nHOME\nLINES\nPATH\nPWD"); - files.insert(b"COLUMNS", b"80"); - files.insert(b"LINES", b"30"); - files.insert(b"HOME", b"initfs:bin/"); - files.insert(b"PATH", b"initfs:bin/"); - files.insert(b"PWD", b"initfs:bin/"); - EnvScheme { next_id: AtomicUsize::new(0), - files: files, handles: RwLock::new(BTreeMap::new()) } } @@ -42,31 +34,69 @@ impl EnvScheme { impl Scheme for EnvScheme { fn open(&self, path: &[u8], _flags: usize) -> Result { let path = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?.trim_matches('/'); - let data = self.files.get(path.as_bytes()).ok_or(Error::new(ENOENT))?; - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - data: data, - mode: if path.is_empty() { MODE_DIR } else { MODE_FILE }, - seek: 0 - }); + let env_lock = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + context.env.clone() + }; - Ok(id) + if path.is_empty() { + let mut list = Vec::new(); + { + let env = env_lock.lock(); + for entry in env.iter() { + if ! list.is_empty() { + list.push(b'\n'); + } + list.extend_from_slice(&entry.0); + list.push(b'='); + list.extend_from_slice(&entry.1.lock()); + } + } + + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.write().insert(id, Handle { + data: Arc::new(Mutex::new(list)), + mode: MODE_FILE, + seek: 0 + }); + + Ok(id) + } else { + let data = { + let mut env = env_lock.lock(); + if env.contains_key(path.as_bytes()) { + env[path.as_bytes()].clone() + } else /*if flags & O_CREAT == O_CREAT*/ { + let name = path.as_bytes().to_vec().into_boxed_slice(); + let data = Arc::new(Mutex::new(Vec::new())); + env.insert(name, data.clone()); + data + } + }; + + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.write().insert(id, Handle { + data: data, + mode: MODE_FILE, + seek: 0 + }); + + Ok(id) + } } fn dup(&self, id: usize) -> Result { - let (data, mode, seek) = { + let new_handle = { let handles = self.handles.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - (handle.data, handle.mode, handle.seek) + handle.clone() }; let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - data: data, - mode: mode, - seek: seek - }); + self.handles.write().insert(id, new_handle); Ok(id) } @@ -75,9 +105,33 @@ impl Scheme for EnvScheme { let mut handles = self.handles.write(); let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let data = handle.data.lock(); + let mut i = 0; - while i < buffer.len() && handle.seek < handle.data.len() { - buffer[i] = handle.data[handle.seek]; + while i < buffer.len() && handle.seek < data.len() { + buffer[i] = data[handle.seek]; + i += 1; + handle.seek += 1; + } + + Ok(i) + } + + fn write(&self, id: usize, buffer: &[u8]) -> Result { + let mut handles = self.handles.write(); + let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + + let mut data = handle.data.lock(); + + let mut i = 0; + while i < buffer.len() && handle.seek < data.len() { + data[handle.seek] = buffer[i]; + i += 1; + handle.seek += 1; + } + + while i < buffer.len() { + data.push(buffer[i]); i += 1; handle.seek += 1; } @@ -89,10 +143,11 @@ impl Scheme for EnvScheme { let mut handles = self.handles.write(); let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let len = handle.data.lock().len(); handle.seek = match whence { - SEEK_SET => cmp::min(handle.data.len(), pos), - SEEK_CUR => cmp::max(0, cmp::min(handle.data.len() as isize, handle.seek as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(handle.data.len() as isize, handle.data.len() as isize + pos as isize)) as usize, + SEEK_SET => cmp::min(len, pos), + SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.seek as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, _ => return Err(Error::new(EINVAL)) }; @@ -104,12 +159,31 @@ impl Scheme for EnvScheme { let handle = handles.get(&id).ok_or(Error::new(EBADF))?; stat.st_mode = handle.mode; - stat.st_size = handle.data.len() as u32; //TODO: st_size 64-bit + stat.st_size = handle.data.lock().len() as u32; //TODO: st_size 64-bit Ok(0) } - fn fsync(&self, _id: usize) -> Result { + fn fsync(&self, id: usize) -> Result { + let handles = self.handles.read(); + let _handle = handles.get(&id).ok_or(Error::new(EBADF))?; + + Ok(0) + } + + fn ftruncate(&self, id: usize, len: usize) -> Result { + let handles = self.handles.read(); + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; + + let mut data = handle.data.lock(); + if len < data.len() { + data.truncate(len) + } else { + while len > data.len() { + data.push(0); + } + } + Ok(0) } diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs index 646a05c..2fef6f6 100644 --- a/kernel/syscall/fs.rs +++ b/kernel/syscall/fs.rs @@ -152,6 +152,24 @@ pub fn fsync(fd: usize) -> Result { scheme.fsync(file.number) } +/// Truncate the file descriptor +pub fn ftruncate(fd: usize, len: usize) -> Result { + let file = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + let file = context.get_file(fd).ok_or(Error::new(EBADF))?; + file + }; + + let scheme = { + let schemes = scheme::schemes(); + let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; + scheme.clone() + }; + scheme.ftruncate(file.number, len) +} + /// Seek to an offset pub fn lseek(fd: usize, pos: usize, whence: usize) -> Result { let file = { diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs index 2c507ea..c4ed06b 100644 --- a/kernel/syscall/mod.rs +++ b/kernel/syscall/mod.rs @@ -39,6 +39,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_FSTAT => fstat(b, &mut validate_slice_mut(c as *mut Stat, 1)?[0]), SYS_DUP => dup(b), SYS_BRK => brk(b), + SYS_FTRUNCATE => ftruncate(b, c), SYS_IOPL => iopl(b), SYS_FSYNC => fsync(b), SYS_CLONE => clone(b, stack), diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index bc61d38..0da2d00 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -66,6 +66,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let mut stack_option = None; let grants; let cwd; + let env; let files; // Copy from old process @@ -181,6 +182,12 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { cwd = Arc::new(Mutex::new(context.cwd.lock().clone())); } + if flags & CLONE_VM == CLONE_VM { + env = context.env.clone(); + } else { + env = Arc::new(Mutex::new(context.env.lock().clone())); + } + if flags & CLONE_FILES == CLONE_FILES { files = context.files.clone(); } else { @@ -339,6 +346,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { context.cwd = cwd; + context.env = env; + context.files = files; context.arch.set_page_table(unsafe { new_table.address() }); diff --git a/libstd b/libstd index 552fab1..9f7687e 160000 --- a/libstd +++ b/libstd @@ -1 +1 @@ -Subproject commit 552fab1400b4eb7b4dbe14adf109d167db5ac082 +Subproject commit 9f7687ec7cf09945b8d832e4777b6c521f408754 diff --git a/programs/login/src/main.rs b/programs/login/src/main.rs index b885a6b..6bd6ba4 100644 --- a/programs/login/src/main.rs +++ b/programs/login/src/main.rs @@ -25,6 +25,13 @@ pub fn main() { for arg in sh_args.iter() { command.arg(arg); } + + command.env("HOME", "initfs:"); + command.env("PWD", "initfs:bin/"); + command.env("PATH", "initfs:bin/"); + command.env("COLUMNS", "80"); + command.env("LINES", "30"); + command.env("TTY", &tty); match command.spawn() { Ok(mut child) => match child.wait() {