From 2fffe3ee779feeb2b633a5fa416c00f06a5ea0bf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 11 Sep 2016 17:31:21 -0600 Subject: [PATCH] Fix close, add dup --- kernel/context/mod.rs | 19 +++++++++++++++++++ kernel/scheme/debug.rs | 4 ++++ kernel/scheme/initfs.rs | 25 ++++++++++++++++++------- kernel/scheme/mod.rs | 11 ++++++++--- kernel/syscall/fs.rs | 24 ++++++++++++++++++++---- kernel/syscall/mod.rs | 4 ++++ 6 files changed, 73 insertions(+), 14 deletions(-) diff --git a/kernel/context/mod.rs b/kernel/context/mod.rs index 506dde6..8975582 100644 --- a/kernel/context/mod.rs +++ b/kernel/context/mod.rs @@ -202,4 +202,23 @@ impl Context { None } } + + /// Get a file + pub fn get_file(&self, i: usize) -> Option { + if i < self.files.len() { + self.files[i] + } else { + None + } + } + + /// Remove a file + // TODO: adjust files vector to smaller size if possible + pub fn remove_file(&mut self, i: usize) -> Option { + if i < self.files.len() { + self.files[i].take() + } else { + None + } + } } diff --git a/kernel/scheme/debug.rs b/kernel/scheme/debug.rs index 942cc4a..0623b8b 100644 --- a/kernel/scheme/debug.rs +++ b/kernel/scheme/debug.rs @@ -10,6 +10,10 @@ impl Scheme for DebugScheme { Ok(0) } + fn dup(&mut self, _file: usize) -> Result { + Ok(0) + } + /// Read the file `number` into the `buffer` /// /// Returns the number of bytes read diff --git a/kernel/scheme/initfs.rs b/kernel/scheme/initfs.rs index 1014fe7..d947b5a 100644 --- a/kernel/scheme/initfs.rs +++ b/kernel/scheme/initfs.rs @@ -33,18 +33,33 @@ impl InitFsScheme { impl Scheme for InitFsScheme { fn open(&mut self, path: &[u8], _flags: usize) -> Result { let data = self.files.get(path).ok_or(Error::NoEntry)?; + let id = self.next_id; self.next_id += 1; self.handles.insert(id, Handle { data: data, seek: 0 }); + + Ok(id) + } + + fn dup(&mut self, file: usize) -> Result { + let (data, seek) = { + let handle = self.handles.get(&file).ok_or(Error::BadFile)?; + (handle.data, handle.seek) + }; + + let id = self.next_id; + self.next_id += 1; + self.handles.insert(id, Handle { + data: data, + seek: seek + }); + Ok(id) } - /// Read the file `number` into the `buffer` - /// - /// Returns the number of bytes read fn read(&mut self, file: usize, buffer: &mut [u8]) -> Result { let mut handle = self.handles.get_mut(&file).ok_or(Error::BadFile)?; @@ -58,14 +73,10 @@ impl Scheme for InitFsScheme { Ok(i) } - /// Write the `buffer` to the `file` - /// - /// Returns the number of bytes written fn write(&mut self, _file: usize, _buffer: &[u8]) -> Result { Err(Error::NotPermitted) } - /// Close the file `number` fn close(&mut self, file: usize) -> Result<()> { self.handles.remove(&file).ok_or(Error::BadFile).and(Ok(())) } diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs index ef86570..a2a8009 100644 --- a/kernel/scheme/mod.rs +++ b/kernel/scheme/mod.rs @@ -113,16 +113,21 @@ pub trait Scheme { /// Returns a file descriptor or an error fn open(&mut self, path: &[u8], flags: usize) -> Result; + /// Duplicate an open file descriptor + /// + /// Returns a file descriptor or an error + fn dup(&mut self, file: usize) -> Result; + /// Read from some file descriptor into the `buffer` /// /// Returns the number of bytes read - fn read(&mut self, fd: usize, buffer: &mut [u8]) -> Result; + fn read(&mut self, file: usize, buffer: &mut [u8]) -> Result; /// Write the `buffer` to the file descriptor /// /// Returns the number of bytes written - fn write(&mut self, fd: usize, buffer: &[u8]) -> Result; + fn write(&mut self, file: usize, buffer: &[u8]) -> Result; /// Close the file descriptor - fn close(&mut self, fd: usize) -> Result<()>; + fn close(&mut self, file: usize) -> Result<()>; } diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs index fed9bc7..ddb4f8a 100644 --- a/kernel/syscall/fs.rs +++ b/kernel/syscall/fs.rs @@ -11,7 +11,7 @@ pub fn read(fd: usize, buf: &mut [u8]) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::NoProcess)?; let context = context_lock.read(); - let file = context.files.get(fd).ok_or(Error::BadFile)?.ok_or(Error::BadFile)?; + let file = context.get_file(fd).ok_or(Error::BadFile)?; file }; @@ -27,7 +27,7 @@ pub fn write(fd: usize, buf: &[u8]) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::NoProcess)?; let context = context_lock.read(); - let file = context.files.get(fd).ok_or(Error::BadFile)?.ok_or(Error::BadFile)?; + let file = context.get_file(fd).ok_or(Error::BadFile)?; file }; @@ -65,8 +65,8 @@ pub fn close(fd: usize) -> Result { let file = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::NoProcess)?; - let context = context_lock.read(); - let file = context.files.get(fd).ok_or(Error::BadFile)?.ok_or(Error::BadFile)?; + let mut context = context_lock.write(); + let file = context.remove_file(fd).ok_or(Error::BadFile)?; file }; @@ -75,3 +75,19 @@ pub fn close(fd: usize) -> Result { let result = scheme_mutex.lock().close(file.number).and(Ok(0)); result } + +/// Duplicate file descriptor +pub fn dup(fd: usize) -> Result { + let file = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::NoProcess)?; + let context = context_lock.read(); + let file = context.get_file(fd).ok_or(Error::BadFile)?; + file + }; + + let schemes = scheme::schemes(); + let scheme_mutex = schemes.get(file.scheme).ok_or(Error::BadFile)?; + let result = scheme_mutex.lock().dup(file.number); + result +} diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs index 0af4628..3fdb7a5 100644 --- a/kernel/syscall/mod.rs +++ b/kernel/syscall/mod.rs @@ -30,6 +30,8 @@ pub enum Call { Exec = 11, /// Get process ID GetPid = 20, + /// Duplicate file descriptor + Dup = 41, /// Set process break Brk = 45, /// Set process I/O privilege level @@ -52,6 +54,7 @@ impl Call { 6 => Ok(Call::Close), 11 => Ok(Call::Exec), 20 => Ok(Call::GetPid), + 41 => Ok(Call::Dup), 45 => Ok(Call::Brk), 110 => Ok(Call::Iopl), 120 => Ok(Call::Clone), @@ -112,6 +115,7 @@ pub fn handle(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize) -> Re Call::Close => close(b), Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?), Call::GetPid => getpid(), + Call::Dup => dup(b), Call::Brk => brk(b), Call::Iopl => iopl(b), Call::Clone => clone(b),