From 3db0c2a4b1011a90b9d790f8be89436d07318166 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 15 Mar 2017 19:42:11 -0600 Subject: [PATCH] Fix handling of missing files --- mount/redox/scheme.rs | 161 +++++++++++++++++++++--------------------- src/filesystem.rs | 15 ---- 2 files changed, 81 insertions(+), 95 deletions(-) diff --git a/mount/redox/scheme.rs b/mount/redox/scheme.rs index 6886c4d89e..d5aa3f0d19 100644 --- a/mount/redox/scheme.rs +++ b/mount/redox/scheme.rs @@ -30,6 +30,39 @@ impl FileScheme { } } +fn path_nodes(fs: &mut FileSystem, path: &str, uid: u32, gid: u32, nodes: &mut Vec<(u64, Node)>) -> Result> { + let mut parts = path.split('/').filter(|part| ! part.is_empty()); + let mut part_opt = None; + let mut block = fs.header.1.root; + loop { + let node_res = match part_opt { + None => fs.node(block), + Some(part) => fs.find_node(part, block), + }; + + part_opt = parts.next(); + if part_opt.is_some() { + let node = node_res?; + if ! node.1.permission(uid, gid, Node::MODE_EXEC) { + return Err(Error::new(EACCES)); + } + if ! node.1.is_dir() { + return Err(Error::new(ENOTDIR)); + } + block = node.0; + nodes.push(node); + } else { + match node_res { + Ok(node) => return Ok(Some(node)), + Err(err) => match err.errno { + ENOENT => return Ok(None), + _ => return Err(err) + } + } + } + } +} + impl Scheme for FileScheme { fn open(&self, url: &[u8], flags: usize, uid: u32, gid: u32) -> Result { let path = str::from_utf8(url).unwrap_or("").trim_matches('/'); @@ -39,19 +72,9 @@ impl Scheme for FileScheme { let mut fs = self.fs.borrow_mut(); let mut nodes = Vec::new(); - let node_result = fs.path_nodes(path, &mut nodes); - for node in nodes.iter() { - if ! node.1.permission(uid, gid, Node::MODE_EXEC) { - // 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 = match node_result { - Ok(node) => if flags & (O_CREAT | O_EXCL) == O_CREAT | O_EXCL { + let node_opt = path_nodes(&mut fs, path, uid, gid, &mut nodes)?; + let resource: Box = match node_opt { + 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 { @@ -112,7 +135,7 @@ impl Scheme for FileScheme { Box::new(FileResource::new(path.to_string(), node.0, flags)) }, - Err(err) => if err.errno == ENOENT && flags & O_CREAT == O_CREAT { + None => if flags & O_CREAT == O_CREAT { let mut last_part = String::new(); for part in path.split('/') { if ! part.is_empty() { @@ -155,7 +178,7 @@ impl Scheme for FileScheme { return Err(Error::new(EPERM)); } } else { - return Err(err); + return Err(Error::new(ENOENT)); } }; @@ -173,24 +196,16 @@ impl Scheme for FileScheme { let mut fs = self.fs.borrow_mut(); let mut nodes = Vec::new(); - let node_result = fs.path_nodes(path, &mut nodes); - for node in nodes.iter() { - if ! node.1.permission(uid, gid, Node::MODE_EXEC) { - // println!("dir not executable {:o}", node.1.mode); - return Err(Error::new(EACCES)); + if let Some(mut node) = path_nodes(&mut fs, path, uid, gid, &mut nodes)? { + if node.1.uid == uid || uid == 0 { + node.1.mode = (node.1.mode & ! MODE_PERM) | (mode & MODE_PERM); + try!(fs.write_at(node.0, &node.1)); + Ok(0) + } else { + Err(Error::new(EPERM)) } - if ! node.1.is_dir() { - return Err(Error::new(ENOTDIR)); - } - } - - let mut node = node_result?; - if node.1.uid == uid || uid == 0 { - node.1.mode = (node.1.mode & ! MODE_PERM) | (mode & MODE_PERM); - try!(fs.write_at(node.0, &node.1)); - Ok(0) } else { - Err(Error::new(EPERM)) + Err(Error::new(ENOENT)) } } @@ -202,39 +217,32 @@ impl Scheme for FileScheme { let mut fs = self.fs.borrow_mut(); let mut nodes = Vec::new(); - let child = try!(fs.path_nodes(path, &mut nodes)); - for node in nodes.iter() { - if ! node.1.permission(uid, gid, Node::MODE_EXEC) { - // 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() { - if ! parent.1.permission(uid, gid, Node::MODE_WRITE) { - // println!("dir not writable {:o}", parent.1.mode); - return Err(Error::new(EACCES)); - } - - if child.1.is_dir() { - if ! child.1.permission(uid, gid, Node::MODE_WRITE) { + if let Some(child) = path_nodes(&mut fs, path, uid, gid, &mut nodes)? { + if let Some(parent) = nodes.last() { + if ! parent.1.permission(uid, gid, Node::MODE_WRITE) { // println!("dir not writable {:o}", parent.1.mode); return Err(Error::new(EACCES)); } - if let Ok(child_name) = child.1.name() { - fs.remove_node(Node::MODE_DIR, child_name, parent.0).and(Ok(0)) + if child.1.is_dir() { + if ! child.1.permission(uid, gid, Node::MODE_WRITE) { + // println!("dir not writable {:o}", parent.1.mode); + return Err(Error::new(EACCES)); + } + + if let Ok(child_name) = child.1.name() { + fs.remove_node(Node::MODE_DIR, child_name, parent.0).and(Ok(0)) + } else { + Err(Error::new(ENOENT)) + } } else { - Err(Error::new(ENOENT)) + Err(Error::new(ENOTDIR)) } } else { - Err(Error::new(ENOTDIR)) + Err(Error::new(EPERM)) } } else { - Err(Error::new(EPERM)) + Err(Error::new(ENOENT)) } } @@ -246,39 +254,32 @@ impl Scheme for FileScheme { let mut fs = self.fs.borrow_mut(); let mut nodes = Vec::new(); - let child = try!(fs.path_nodes(path, &mut nodes)); - for node in nodes.iter() { - if ! node.1.permission(uid, gid, Node::MODE_EXEC) { - // 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() { - if ! parent.1.permission(uid, gid, Node::MODE_WRITE) { - // println!("dir not writable {:o}", parent.1.mode); - return Err(Error::new(EACCES)); - } - - if ! child.1.is_dir() { - if ! child.1.permission(uid, gid, Node::MODE_WRITE) { - // println!("file not writable {:o}", parent.1.mode); + if let Some(child) = path_nodes(&mut fs, path, uid, gid, &mut nodes)? { + if let Some(parent) = nodes.last() { + if ! parent.1.permission(uid, gid, Node::MODE_WRITE) { + // println!("dir not writable {:o}", parent.1.mode); return Err(Error::new(EACCES)); } - if let Ok(child_name) = child.1.name() { - fs.remove_node(Node::MODE_FILE, child_name, parent.0).and(Ok(0)) + if ! child.1.is_dir() { + if ! child.1.permission(uid, gid, Node::MODE_WRITE) { + // println!("file not writable {:o}", parent.1.mode); + return Err(Error::new(EACCES)); + } + + if let Ok(child_name) = child.1.name() { + fs.remove_node(Node::MODE_FILE, child_name, parent.0).and(Ok(0)) + } else { + Err(Error::new(ENOENT)) + } } else { - Err(Error::new(ENOENT)) + Err(Error::new(EISDIR)) } } else { - Err(Error::new(EISDIR)) + Err(Error::new(EPERM)) } } else { - Err(Error::new(EPERM)) + Err(Error::new(ENOENT)) } } diff --git a/src/filesystem.rs b/src/filesystem.rs index 19f8be25a8..f420364888 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -152,21 +152,6 @@ impl FileSystem { self.find_node(name, parent.1.next) } - pub fn path_nodes(&mut self, path: &str, nodes: &mut Vec<(u64, Node)>) -> Result<(u64, Node)> { - let mut block = self.header.1.root; - nodes.push(try!(self.node(block))); - - for part in path.split('/') { - if ! part.is_empty() { - let node = try!(self.find_node(part, block)); - block = node.0; - nodes.push(node); - } - } - - Ok(nodes.pop().unwrap()) - } - fn insert_blocks(&mut self, block: u64, length: u64, parent_block: u64) -> Result<()> { if parent_block == 0 { return Err(Error::new(ENOSPC));