diff --git a/src/scheme/root.rs b/src/scheme/root.rs index cd08fd3..42bcaad 100644 --- a/src/scheme/root.rs +++ b/src/scheme/root.rs @@ -14,7 +14,8 @@ pub struct RootScheme { scheme_ns: SchemeNamespace, scheme_id: SchemeId, next_id: AtomicUsize, - handles: RwLock>> + handles: RwLock>>, + ls_handles: RwLock>, } impl RootScheme { @@ -23,14 +24,26 @@ impl RootScheme { scheme_ns: scheme_ns, scheme_id: scheme_id, next_id: AtomicUsize::new(0), - handles: RwLock::new(BTreeMap::new()) + handles: RwLock::new(BTreeMap::new()), + ls_handles: RwLock::new(BTreeMap::new()), } } } impl Scheme for RootScheme { fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { + use syscall::flag::*; + if uid == 0 { + if flags & O_DIRECTORY == O_DIRECTORY { + if flags & O_ACCMODE != O_RDONLY { + return Err(Error::new(EACCES)); + } + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.ls_handles.write().insert(id, AtomicUsize::new(0)); + return Ok(id); + } + let context = { let contexts = context::contexts(); let context = contexts.current().ok_or(Error::new(ESRCH))?; @@ -74,11 +87,46 @@ impl Scheme for RootScheme { fn read(&self, file: usize, buf: &mut [u8]) -> Result { let inner = { let handles = self.handles.read(); - let inner = handles.get(&file).ok_or(Error::new(EBADF))?; - inner.clone() + handles.get(&file).map(Clone::clone) }; - inner.read(buf) + if let Some(inner) = inner { + inner.read(buf) + } else { + let scheme_ns = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + context.ens + }; + + let schemes = scheme::schemes(); + let mut schemes_iter = schemes.iter_name(scheme_ns); + + let num = { + let handles = self.ls_handles.read(); + let inner = handles.get(&file).ok_or(Error::new(EBADF))?; + inner.load(Ordering::SeqCst) + }; + + if let Some(scheme) = schemes_iter.nth(num) { + let mut i = 0; + while i < buf.len() && i < scheme.0.len() { + buf[i] = scheme.0[i]; + i += 1; + } + + { + let handles = self.ls_handles.read(); + let inner = handles.get(&file).ok_or(Error::new(EBADF))?; + inner.fetch_add(1, Ordering::SeqCst) + }; + + Ok(i) + } else { + Ok(0) + } + } } fn write(&self, file: usize, buf: &[u8]) -> Result { @@ -136,6 +184,9 @@ impl Scheme for RootScheme { } fn close(&self, file: usize) -> Result { - self.handles.write().remove(&file).ok_or(Error::new(EBADF)).and(Ok(0)) + if self.handles.write().remove(&file).is_none() { + self.ls_handles.write().remove(&file).ok_or(Error::new(EBADF))?; + } + Ok(0) } }