diff --git a/Makefile b/Makefile index 6b8d129..0a23bf8 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ clean: cargo clean --manifest-path programs/init/Cargo.toml cargo clean --manifest-path programs/ion/Cargo.toml cargo clean --manifest-path programs/login/Cargo.toml + cargo clean --manifest-path programs/coreutils/Cargo.toml cargo clean --manifest-path schemes/example/Cargo.toml rm -rf initfs/bin rm -rf build @@ -163,7 +164,8 @@ coreutils: \ initfs/bin/env \ initfs/bin/ls \ initfs/bin/printenv \ - initfs/bin/pwd + initfs/bin/pwd \ + initfs/bin/realpath $(BUILD)/initfs.rs: \ initfs/bin/pcid \ diff --git a/kernel/scheme/initfs.rs b/kernel/scheme/initfs.rs index e3f1d40..d23adc7 100644 --- a/kernel/scheme/initfs.rs +++ b/kernel/scheme/initfs.rs @@ -12,6 +12,7 @@ use syscall::scheme::Scheme; mod gen; struct Handle { + path: &'static [u8], data: &'static [u8], mode: u16, seek: usize @@ -35,28 +36,37 @@ impl InitFsScheme { impl Scheme for InitFsScheme { fn open(&self, path: &[u8], _flags: usize) -> Result { - let path = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?.trim_matches('/'); - let file = self.files.get(path.as_bytes()).ok_or(Error::new(ENOENT))?; + let path_utf8 = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?; + let path_trimmed = path_utf8.trim_matches('/'); - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - data: file.0, - mode: if file.1 { MODE_DIR } else { MODE_FILE }, - seek: 0 - }); + //Have to iterate to get the path without allocation + for entry in self.files.iter() { + if entry.0 == &path_trimmed.as_bytes() { + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.write().insert(id, Handle { + path: entry.0, + data: (entry.1).0, + mode: if (entry.1).1 { MODE_DIR } else { MODE_FILE }, + seek: 0 + }); - Ok(id) + return Ok(id) + } + } + + Err(Error::new(ENOENT)) } fn dup(&self, id: usize) -> Result { - let (data, mode, seek) = { + let (path, data, mode, seek) = { let handles = self.handles.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - (handle.data, handle.mode, handle.seek) + (handle.path, handle.data, handle.mode, handle.seek) }; let id = self.next_id.fetch_add(1, Ordering::SeqCst); self.handles.write().insert(id, Handle { + path: path, data: data, mode: mode, seek: seek @@ -93,6 +103,28 @@ impl Scheme for InitFsScheme { Ok(handle.seek) } + fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { + let handles = self.handles.read(); + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; + + //TODO: Copy scheme part in kernel + let mut i = 0; + let scheme_path = b"initfs:"; + while i < buf.len() && i < scheme_path.len() { + buf[i] = scheme_path[i]; + i += 1; + } + + let mut j = 0; + while i < buf.len() && j < handle.path.len() { + buf[i] = handle.path[j]; + i += 1; + j += 1; + } + + Ok(i) + } + fn fstat(&self, id: usize, stat: &mut Stat) -> Result { let handles = self.handles.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs index 029222b..646a05c 100644 --- a/kernel/syscall/fs.rs +++ b/kernel/syscall/fs.rs @@ -98,6 +98,24 @@ pub fn dup(fd: usize) -> Result { scheme.dup(file.number) } +/// Get the canonical path of the file +pub fn fpath(fd: usize, buf: &mut [u8]) -> 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.fpath(file.number, buf) +} + /// Get information about the file pub fn fstat(fd: usize, stat: &mut Stat) -> Result { let file = { diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs index 4befeb7..2c507ea 100644 --- a/kernel/syscall/mod.rs +++ b/kernel/syscall/mod.rs @@ -44,6 +44,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_CLONE => clone(b, stack), SYS_YIELD => sched_yield(), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), + SYS_FPATH => fpath(b, validate_slice_mut(c as *mut u8, d)?), SYS_PHYSMAP => physmap(b, c, d), SYS_PHYSUNMAP => physunmap(b), _ => {