diff --git a/scheme/initfs.rs b/scheme/initfs.rs index e3f1d4006b912576d03b07b9dd6abc8b2186dfb5..d23adc755e42ea11193912eff23e1e46bf222479 100644 --- a/scheme/initfs.rs +++ b/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<usize> { - 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 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 - }); + let path_utf8 = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?; + let path_trimmed = path_utf8.trim_matches('/'); + + //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 + }); + + return Ok(id) + } + } - Ok(id) + Err(Error::new(ENOENT)) } fn dup(&self, id: usize) -> Result<usize> { - 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<usize> { + 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<usize> { let handles = self.handles.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; diff --git a/syscall/fs.rs b/syscall/fs.rs index 029222b78297fbc2b8010a9b5792eac8e316fdae..646a05ca6c6a0ba86da03f6f608698b513c67534 100644 --- a/syscall/fs.rs +++ b/syscall/fs.rs @@ -98,6 +98,24 @@ pub fn dup(fd: usize) -> Result<usize> { scheme.dup(file.number) } +/// Get the canonical path of the file +pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> { + 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<usize> { let file = { diff --git a/syscall/mod.rs b/syscall/mod.rs index 4befeb782c28c9edfd8d36048c70c9ee350be79f..2c507ea4f219218cdbff8d2a9763333200cc1eb3 100644 --- a/syscall/mod.rs +++ b/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), _ => {