diff --git a/scheme/resource.rs b/scheme/resource.rs index 12765154191d4381d825cb046a631daf6ca25999..ab756e578fdc473253f07bdaccd9fab8a9eb5f35 100644 --- a/scheme/resource.rs +++ b/scheme/resource.rs @@ -2,7 +2,8 @@ use redoxfs::FileSystem; use std::cmp::{min, max}; -use syscall::error::{Error, Result, EINVAL}; +use syscall::error::{Error, Result, EBADF, EINVAL}; +use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR}; use syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END}; pub trait Resource { @@ -55,7 +56,7 @@ impl Resource for DirResource { } fn write(&mut self, _buf: &[u8], _fs: &mut FileSystem) -> Result<usize> { - Err(Error::new(EINVAL)) + Err(Error::new(EBADF)) } fn seek(&mut self, offset: usize, whence: usize, _fs: &mut FileSystem) -> Result<usize> { @@ -93,25 +94,27 @@ impl Resource for DirResource { } fn sync(&mut self) -> Result<usize> { - Err(Error::new(EINVAL)) + Err(Error::new(EBADF)) } fn truncate(&mut self, _len: usize, _fs: &mut FileSystem) -> Result<usize> { - Err(Error::new(EINVAL)) + Err(Error::new(EBADF)) } } pub struct FileResource { path: String, block: u64, + flags: usize, seek: u64, } impl FileResource { - pub fn new(path: String, block: u64) -> FileResource { + pub fn new(path: String, block: u64, flags: usize) -> FileResource { FileResource { path: path, block: block, + flags: flags, seek: 0, } } @@ -122,20 +125,29 @@ impl Resource for FileResource { Ok(Box::new(FileResource { path: self.path.clone(), block: self.block, + flags: self.flags, seek: self.seek, })) } fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem) -> Result<usize> { - let count = try!(fs.read_node(self.block, self.seek, buf)); - self.seek += count as u64; - Ok(count) + if self.flags & O_ACCMODE == O_RDWR || self.flags & O_ACCMODE == O_RDONLY { + let count = try!(fs.read_node(self.block, self.seek, buf)); + self.seek += count as u64; + Ok(count) + } else { + Err(Error::new(EBADF)) + } } fn write(&mut self, buf: &[u8], fs: &mut FileSystem) -> Result<usize> { - let count = try!(fs.write_node(self.block, self.seek, buf)); - self.seek += count as u64; - Ok(count) + if self.flags & O_ACCMODE == O_RDWR || self.flags & O_ACCMODE == O_WRONLY { + let count = try!(fs.write_node(self.block, self.seek, buf)); + self.seek += count as u64; + Ok(count) + } else { + Err(Error::new(EBADF)) + } } fn seek(&mut self, offset: usize, whence: usize, fs: &mut FileSystem) -> Result<usize> { @@ -179,8 +191,11 @@ impl Resource for FileResource { } fn truncate(&mut self, len: usize, fs: &mut FileSystem) -> Result<usize> { - try!(fs.node_set_len(self.block, len as u64)); - - Ok(0) + if self.flags & O_ACCMODE == O_RDWR || self.flags & O_ACCMODE == O_WRONLY { + try!(fs.node_set_len(self.block, len as u64)); + Ok(0) + } else { + Err(Error::new(EBADF)) + } } } diff --git a/scheme/scheme.rs b/scheme/scheme.rs index 6f64dc10e8c525392adad6fb4c54c3f3d9bbb5ea..3270bdbd2374407b6092daaaee6161e3363d53ec 100644 --- a/scheme/scheme.rs +++ b/scheme/scheme.rs @@ -7,9 +7,10 @@ use std::collections::BTreeMap; use std::str; use std::sync::atomic::{AtomicUsize, Ordering}; +use syscall::data::Stat; use syscall::error::{Error, Result, EACCES, EEXIST, EISDIR, ENOTDIR, EPERM, ENOENT, EBADF}; +use syscall::flag::{O_CREAT, O_TRUNC, O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR}; use syscall::scheme::Scheme; -use syscall::{Stat, O_CREAT, O_TRUNC}; pub struct FileScheme { name: &'static str, @@ -44,10 +45,18 @@ impl Scheme for FileScheme { // println!("dir not executable {:o}", node.1.mode); return Err(Error::new(EACCES)); } + if ! node.1.is_dir() { + return Err(Error::new(ENOTDIR)); + } } let resource: Box<Resource> = match node_result { Ok(node) => if node.1.is_dir() { + if flags & O_ACCMODE != O_RDONLY { + // println!("dir not opened with O_RDONLY"); + return Err(Error::new(EACCES)); + } + if ! node.1.permission(uid, gid, Node::MODE_READ) { // println!("dir not readable {:o}", node.1.mode); return Err(Error::new(EACCES)); @@ -67,11 +76,16 @@ impl Scheme for FileScheme { Box::new(DirResource::new(path.to_string(), node.0, data)) } else { - if ! node.1.permission(uid, gid, Node::MODE_READ) { + if (flags & O_ACCMODE == O_RDONLY || flags & O_ACCMODE == O_RDWR) && ! node.1.permission(uid, gid, Node::MODE_READ) { // println!("file not readable {:o}", node.1.mode); return Err(Error::new(EACCES)); } + if (flags & O_ACCMODE == O_WRONLY || flags & O_ACCMODE == O_RDWR) && ! node.1.permission(uid, gid, Node::MODE_WRITE) { + // println!("file not writable {:o}", node.1.mode); + return Err(Error::new(EACCES)); + } + if flags & O_TRUNC == O_TRUNC { if ! node.1.permission(uid, gid, Node::MODE_WRITE) { // println!("file not writable {:o}", node.1.mode); @@ -81,7 +95,7 @@ impl Scheme for FileScheme { try!(fs.node_set_len(node.0, 0)); } - Box::new(FileResource::new(path.to_string(), node.0)) + Box::new(FileResource::new(path.to_string(), node.0, flags)) }, Err(err) => if err.errno == ENOENT && flags & O_CREAT == O_CREAT { let mut last_part = String::new(); @@ -101,7 +115,18 @@ impl Scheme for FileScheme { node.1.uid = uid; node.1.gid = gid; try!(fs.write_at(node.0, &node.1)); - Box::new(FileResource::new(path.to_string(), node.0)) + + if (flags & O_ACCMODE == O_RDONLY || flags & O_ACCMODE == O_RDWR) && ! node.1.permission(uid, gid, Node::MODE_READ) { + // println!("file not readable {:o}", node.1.mode); + return Err(Error::new(EACCES)); + } + + if (flags & O_ACCMODE == O_WRONLY || flags & O_ACCMODE == O_RDWR) && ! node.1.permission(uid, gid, Node::MODE_WRITE) { + // println!("file not writable {:o}", node.1.mode); + return Err(Error::new(EACCES)); + } + + Box::new(FileResource::new(path.to_string(), node.0, flags)) } else { return Err(Error::new(EPERM)); } @@ -133,6 +158,9 @@ impl Scheme for FileScheme { // println!("dir not executable {:o}", node.1.mode); return Err(Error::new(EACCES)); } + if ! node.1.is_dir() { + return Err(Error::new(ENOTDIR)); + } } match node_result { @@ -182,6 +210,9 @@ impl Scheme for FileScheme { // println!("dir not executable {:o}", node.1.mode); return Err(Error::new(EACCES)); } + if ! node.1.is_dir() { + return Err(Error::new(ENOTDIR)); + } } if let Some(parent) = nodes.last() { @@ -223,6 +254,9 @@ impl Scheme for FileScheme { // println!("dir not executable {:o}", node.1.mode); return Err(Error::new(EACCES)); } + if ! node.1.is_dir() { + return Err(Error::new(ENOTDIR)); + } } if let Some(parent) = nodes.last() {