vfs: improve _find() path handling

This commit is contained in:
Mark Poliakov 2025-01-03 11:37:43 +02:00
parent a126118589
commit 3aec9ce556

View File

@ -540,49 +540,44 @@ impl IoContext {
Ok((buffer, node.flatten_hardlink()?))
}
fn _find(&self, mut at: NodeRef, path: &Path, follow_links: bool) -> Result<NodeRef, Error> {
log::debug!("_find({path:?})");
let mut element;
let mut rest = path;
fn _find(&self, mut at: NodeRef, mut path: &Path, follow_link: bool) -> Result<NodeRef, Error> {
while !path.is_empty() {
let (name, tail) = path.split_left();
loop {
(element, rest) = rest.split_left();
let name = match name {
Path::SELF_NAME => {
path = tail;
continue;
}
Path::PARENT_NAME => {
at = at.parent();
if at.mountpoint_target().is_some() {
// Just exited root -> mountpoint, go up to mountpoint's parent
at = at.parent();
}
path = tail;
continue;
}
name => name,
};
if !at.is_directory() {
log::info!("at is not a dir");
return Err(Error::NotADirectory);
}
match element {
Path::PARENT_NAME => {
at = at.parent();
}
Path::SELF_NAME => {}
_ => break,
}
let access = self.check_access(&at, AccessMode::EXEC)?;
let filename = Filename::new(name)?;
let child = at.lookup_or_load(filename, access)?.flatten_hardlink()?;
let follow_links = follow_link || !tail.is_empty();
let child = self._resolve(child, follow_links)?;
at = child;
path = tail;
}
let is_end = element.is_empty() && rest.is_empty();
at = self._resolve(at, follow_links || !is_end)?;
if !at.is_directory() {
return Err(Error::NotADirectory);
}
if element.is_empty() && rest.is_empty() {
return Ok(at);
}
let access = self.check_access(&at, AccessMode::EXEC)?;
let filename = Filename::new(element)?;
let node = at.lookup_or_load(filename, access)?.flatten_hardlink()?;
let node = self._resolve(node, follow_links)?;
if rest.is_empty() {
Ok(node.flatten_hardlink()?)
} else {
self._find(node, rest, follow_links)
}
at.flatten_hardlink()
}
}