From 93f7ec7a558dba356dcf609fedad361adf629b18 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 11 Aug 2017 18:31:42 -0700 Subject: [PATCH 1/3] Make it not an error to open a directory without O_DIRECTORY or O_STAT POSIX says this should work, and some software seems to rely on that. --- mount/redox/scheme.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/mount/redox/scheme.rs b/mount/redox/scheme.rs index 0190eba6df..ffe888eef0 100644 --- a/mount/redox/scheme.rs +++ b/mount/redox/scheme.rs @@ -189,12 +189,7 @@ impl Scheme for FileScheme { Some(node) => if flags & (O_CREAT | O_EXCL) == O_CREAT | O_EXCL { return Err(Error::new(EEXIST)); } else if node.1.is_dir() { - if flags & O_STAT != O_STAT && flags & O_DIRECTORY != O_DIRECTORY { - // println!("{:X} & {:X}: EISDIR {}", flags, O_DIRECTORY, path); - return Err(Error::new(EISDIR)); - } - - if flags & O_ACCMODE == O_RDONLY { + if flags & O_ACCMODE == O_RDONLY && flags & O_DIRECTORY == O_DIRECTORY { if ! node.1.permission(uid, gid, Node::MODE_READ) { // println!("dir not readable {:o}", node.1.mode); return Err(Error::new(EACCES)); @@ -214,11 +209,11 @@ impl Scheme for FileScheme { } Box::new(DirResource::new(path.to_string(), node.0, data)) - } else if flags & O_STAT == O_STAT { - Box::new(DirResource::new(path.to_string(), node.0, Vec::new())) + } else if flags & O_RDONLY == O_RDONLY || flags & O_WRONLY == O_WRONLY { + // println!("{:X} & {:X}: EISDIR {}", flags, O_DIRECTORY, path); + return Err(Error::new(EISDIR)); } else { - // println!("dir not opened with O_RDONLY"); - return Err(Error::new(EACCES)); + Box::new(DirResource::new(path.to_string(), node.0, Vec::new())) } } else if node.1.is_symlink() && !(flags & O_STAT == O_STAT && flags & O_NOFOLLOW == O_NOFOLLOW) && flags & O_SYMLINK != O_SYMLINK { let mut resolve_nodes = Vec::new(); From f474a9fd77e214e9c5d5bdfb4334dc88a59f1346 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Sat, 12 Aug 2017 11:32:39 -0700 Subject: [PATCH 2/3] Actually, O_RDONLY should work with a directory --- mount/redox/scheme.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mount/redox/scheme.rs b/mount/redox/scheme.rs index ffe888eef0..489ec73d40 100644 --- a/mount/redox/scheme.rs +++ b/mount/redox/scheme.rs @@ -189,7 +189,7 @@ impl Scheme for FileScheme { Some(node) => if flags & (O_CREAT | O_EXCL) == O_CREAT | O_EXCL { return Err(Error::new(EEXIST)); } else if node.1.is_dir() { - if flags & O_ACCMODE == O_RDONLY && flags & O_DIRECTORY == O_DIRECTORY { + if flags & O_ACCMODE == O_RDONLY { if ! node.1.permission(uid, gid, Node::MODE_READ) { // println!("dir not readable {:o}", node.1.mode); return Err(Error::new(EACCES)); @@ -209,7 +209,7 @@ impl Scheme for FileScheme { } Box::new(DirResource::new(path.to_string(), node.0, data)) - } else if flags & O_RDONLY == O_RDONLY || flags & O_WRONLY == O_WRONLY { + } else if flags & O_WRONLY == O_WRONLY { // println!("{:X} & {:X}: EISDIR {}", flags, O_DIRECTORY, path); return Err(Error::new(EISDIR)); } else { From f4a3e1dde002801a68a7158434c73a508e5ae0d5 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Sat, 12 Aug 2017 12:25:36 -0700 Subject: [PATCH 3/3] Make read() on directory not opened as O_DIRECTORY return EISDIR --- mount/redox/resource.rs | 18 ++++++++++-------- mount/redox/scheme.rs | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/mount/redox/resource.rs b/mount/redox/resource.rs index 402fbcaeda..da7d230fbb 100644 --- a/mount/redox/resource.rs +++ b/mount/redox/resource.rs @@ -4,7 +4,7 @@ use std::cmp::{min, max}; use std::time::{SystemTime, UNIX_EPOCH}; use syscall::data::TimeSpec; -use syscall::error::{Error, Result, EBADF, EINVAL}; +use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR}; use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL}; use syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END}; @@ -24,12 +24,12 @@ pub trait Resource { pub struct DirResource { path: String, block: u64, - data: Vec, + data: Option>, seek: usize, } impl DirResource { - pub fn new(path: String, block: u64, data: Vec) -> DirResource { + pub fn new(path: String, block: u64, data: Option>) -> DirResource { DirResource { path: path, block: block, @@ -50,9 +50,10 @@ impl Resource for DirResource { } fn read(&mut self, buf: &mut [u8], _fs: &mut FileSystem) -> Result { + let data = self.data.as_ref().ok_or(Error::new(EISDIR))?; let mut i = 0; - while i < buf.len() && self.seek < self.data.len() { - buf[i] = self.data[self.seek]; + while i < buf.len() && self.seek < data.len() { + buf[i] = data[self.seek]; i += 1; self.seek += 1; } @@ -64,10 +65,11 @@ impl Resource for DirResource { } fn seek(&mut self, offset: usize, whence: usize, _fs: &mut FileSystem) -> Result { + let data = self.data.as_ref().ok_or(Error::new(EBADF))?; self.seek = match whence { - SEEK_SET => max(0, min(self.data.len() as isize, offset as isize)) as usize, - SEEK_CUR => max(0, min(self.data.len() as isize, self.seek as isize + offset as isize)) as usize, - SEEK_END => max(0, min(self.data.len() as isize, self.data.len() as isize + offset as isize)) as usize, + SEEK_SET => max(0, min(data.len() as isize, offset as isize)) as usize, + SEEK_CUR => max(0, min(data.len() as isize, self.seek as isize + offset as isize)) as usize, + SEEK_END => max(0, min(data.len() as isize, data.len() as isize + offset as isize)) as usize, _ => return Err(Error::new(EINVAL)) }; diff --git a/mount/redox/scheme.rs b/mount/redox/scheme.rs index 489ec73d40..ca0362e4ae 100644 --- a/mount/redox/scheme.rs +++ b/mount/redox/scheme.rs @@ -208,12 +208,12 @@ impl Scheme for FileScheme { } } - Box::new(DirResource::new(path.to_string(), node.0, data)) + Box::new(DirResource::new(path.to_string(), node.0, Some(data))) } else if flags & O_WRONLY == O_WRONLY { // println!("{:X} & {:X}: EISDIR {}", flags, O_DIRECTORY, path); return Err(Error::new(EISDIR)); } else { - Box::new(DirResource::new(path.to_string(), node.0, Vec::new())) + Box::new(DirResource::new(path.to_string(), node.0, None)) } } else if node.1.is_symlink() && !(flags & O_STAT == O_STAT && flags & O_NOFOLLOW == O_NOFOLLOW) && flags & O_SYMLINK != O_SYMLINK { let mut resolve_nodes = Vec::new(); @@ -285,7 +285,7 @@ impl Scheme for FileScheme { fs.write_at(node.0, &node.1)?; if dir { - Box::new(DirResource::new(path.to_string(), node.0, Vec::new())) + Box::new(DirResource::new(path.to_string(), node.0, None)) } else { let seek = if flags & O_APPEND == O_APPEND { fs.node_len(node.0)?