diff --git a/Makefile b/Makefile index a621b82..e829cb6 100644 --- a/Makefile +++ b/Makefile @@ -174,11 +174,15 @@ $(BUILD)/initfs.rs: \ initfs/bin/login \ coreutils \ initfs/bin/example - echo 'use collections::BTreeMap;' > $@ - echo 'pub fn gen() -> BTreeMap<&'"'"'static [u8], &'"'"'static [u8]> {' >> $@ - echo ' let mut files: BTreeMap<&'"'"'static [u8], &'"'"'static [u8]> = BTreeMap::new();' >> $@ - find initfs -type f -o -type l | cut -d '/' -f2- | sort \ - | awk '{printf(" files.insert(b\"%s\", include_bytes!(\"../../initfs/%s\"));\n", $$0, $$0)}' \ - >> $@ - echo ' files' >> $@ - echo '}' >> $@ + echo 'use collections::BTreeMap;' > $@ + echo 'pub fn gen() -> BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> {' >> $@ + echo ' let mut files: BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> = BTreeMap::new();' >> $@ + for folder in `find initfs -type d`; do \ + name=$$(echo $$folder | sed 's/initfs//' | cut -d '/' -f2-) ; \ + echo -n ' files.insert(b"'$$name'", (b"' >> $@ ; \ + ls -1 $$folder | sort | awk 'NR > 1 {printf("\\n")} {printf("%s", $$0)}' >> $@ ; \ + echo '", true));' >> $@ ; \ + done + find initfs -type f -o -type l | cut -d '/' -f2- | sort | awk '{printf(" files.insert(b\"%s\", (include_bytes!(\"../../initfs/%s\"), false));\n", $$0, $$0)}' >> $@ + echo ' files' >> $@ + echo '}' >> $@ diff --git a/kernel/scheme/env.rs b/kernel/scheme/env.rs index 38ca8a8..5cabbcb 100644 --- a/kernel/scheme/env.rs +++ b/kernel/scheme/env.rs @@ -3,12 +3,14 @@ use core::cmp; use core::sync::atomic::{AtomicUsize, Ordering}; use spin::RwLock; +use syscall::data::Stat; use syscall::error::*; -use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END}; +use syscall::flag::{MODE_DIR, MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END}; use syscall::scheme::Scheme; struct Handle { data: &'static [u8], + mode: u16, seek: usize } @@ -22,11 +24,12 @@ impl EnvScheme { pub fn new() -> EnvScheme { let mut files: BTreeMap<&'static [u8], &'static [u8]> = BTreeMap::new(); - files.insert(b"HOME", b"initfs:bin/"); - files.insert(b"PWD", b"initfs:bin/"); - files.insert(b"PATH", b"initfs:bin/"); + 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), @@ -43,31 +46,33 @@ impl Scheme for EnvScheme { 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 }); Ok(id) } - fn dup(&self, file: usize) -> Result { - let (data, seek) = { + fn dup(&self, id: usize) -> Result { + let (data, mode, seek) = { let handles = self.handles.read(); - let handle = handles.get(&file).ok_or(Error::new(EBADF))?; - (handle.data, handle.seek) + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; + (handle.data, handle.mode, handle.seek) }; let id = self.next_id.fetch_add(1, Ordering::SeqCst); self.handles.write().insert(id, Handle { data: data, + mode: mode, seek: seek }); Ok(id) } - fn read(&self, file: usize, buffer: &mut [u8]) -> Result { + fn read(&self, id: usize, buffer: &mut [u8]) -> Result { let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&file).ok_or(Error::new(EBADF))?; + let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; let mut i = 0; while i < buffer.len() && handle.seek < handle.data.len() { @@ -93,11 +98,21 @@ impl Scheme for EnvScheme { Ok(handle.seek) } - fn fsync(&self, _file: usize) -> Result { + fn fstat(&self, id: usize, stat: &mut Stat) -> Result { + let handles = self.handles.read(); + 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 + Ok(0) } - fn close(&self, file: usize) -> Result { - self.handles.write().remove(&file).ok_or(Error::new(EBADF)).and(Ok(0)) + fn fsync(&self, _id: usize) -> Result { + Ok(0) + } + + fn close(&self, id: usize) -> Result { + self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) } } diff --git a/kernel/scheme/initfs.rs b/kernel/scheme/initfs.rs index 525e0a7..762d051 100644 --- a/kernel/scheme/initfs.rs +++ b/kernel/scheme/initfs.rs @@ -1,10 +1,11 @@ use collections::BTreeMap; -use core::cmp; +use core::{cmp, str}; use core::sync::atomic::{AtomicUsize, Ordering}; use spin::RwLock; +use syscall::data::Stat; use syscall::error::*; -use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END}; +use syscall::flag::{MODE_DIR, MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END}; use syscall::scheme::Scheme; #[path="../../build/userspace/initfs.rs"] @@ -12,12 +13,13 @@ mod gen; struct Handle { data: &'static [u8], + mode: u16, seek: usize } pub struct InitFsScheme { next_id: AtomicUsize, - files: BTreeMap<&'static [u8], &'static [u8]>, + files: BTreeMap<&'static [u8], (&'static [u8], bool)>, handles: RwLock> } @@ -33,11 +35,14 @@ impl InitFsScheme { impl Scheme for InitFsScheme { fn open(&self, path: &[u8], _flags: usize) -> Result { - let data = self.files.get(path).ok_or(Error::new(ENOENT))?; + let path = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?.trim_matches('/'); + println!("{}", path); + 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: data, + data: file.0, + mode: if file.1 { MODE_DIR } else { MODE_FILE }, seek: 0 }); @@ -45,28 +50,29 @@ impl Scheme for InitFsScheme { } fn dup(&self, id: usize) -> Result { - let (data, seek) = { + let (data, mode, seek) = { let handles = self.handles.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - (handle.data, handle.seek) + (handle.data, handle.mode, handle.seek) }; - let new_id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(new_id, Handle { + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.write().insert(id, Handle { data: data, + mode: mode, seek: seek }); - Ok(new_id) + Ok(id) } - fn read(&self, id: usize, buf: &mut [u8]) -> Result { + fn read(&self, id: usize, buffer: &mut [u8]) -> Result { let mut handles = self.handles.write(); let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; let mut i = 0; - while i < buf.len() && handle.seek < handle.data.len() { - buf[i] = handle.data[handle.seek]; + while i < buffer.len() && handle.seek < handle.data.len() { + buffer[i] = handle.data[handle.seek]; i += 1; handle.seek += 1; } @@ -88,6 +94,16 @@ impl Scheme for InitFsScheme { Ok(handle.seek) } + fn fstat(&self, id: usize, stat: &mut Stat) -> Result { + let handles = self.handles.read(); + 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 + + Ok(0) + } + fn fsync(&self, _id: usize) -> Result { Ok(0) } diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs index 5ade167..4befeb7 100644 --- a/kernel/syscall/mod.rs +++ b/kernel/syscall/mod.rs @@ -36,7 +36,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), SYS_LSEEK => lseek(b, c, d), SYS_GETPID => getpid(), - SYS_FSTAT => fstat(b, &mut validate_slice_mut(b as *mut Stat, 1)?[0]), + SYS_FSTAT => fstat(b, &mut validate_slice_mut(c as *mut Stat, 1)?[0]), SYS_DUP => dup(b), SYS_BRK => brk(b), SYS_IOPL => iopl(b),