1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 19:55:06 +00:00

Kernel: Fix awkward bug where "touch /foo/bar/baz" could create "/baz"

To accomodate file creation, path resolution optionally returns the
last valid parent directory seen while traversing the path.

Clients will then interpret "ENOENT, but I have a parent for you" as
meaning that the file doesn't exist, but its immediate parent directory
does. The client then goes ahead and creates a new file.

In the case of "/foo/bar/baz" where there is no "/foo", it would fail
with ENOENT and "/" as the last seen parent directory, causing e.g the
open() syscall to create "/baz".

Covered by test_io.
This commit is contained in:
Andreas Kling 2020-01-03 03:53:06 +01:00
parent 8cc5fa5598
commit 3be1c7b514

View file

@ -692,8 +692,19 @@ KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path(StringView path, Custody& ba
auto& current_parent = custody_chain.last();
crumb_id = crumb_inode->lookup(part);
if (!crumb_id.is_valid())
if (!crumb_id.is_valid()) {
if (i != parts.size() - 1) {
// We didn't find the filename we were looking for,
// and we didn't even reach the last path part.
// (ENOENT with non-null parent_custody) signals to caller that
// we found the immediate parent of the file, but the file itself
// does not exist yet.
// Since this is not the immediate parent, clear parent_custody.
if (parent_custody)
*parent_custody = nullptr;
}
return KResult(-ENOENT);
}
if (auto mount = find_mount_for_host(crumb_id))
crumb_id = mount->guest();
if (inode_was_root_at_head_of_loop && crumb_id.is_root_inode() && !is_vfs_root(crumb_id) && part == "..") {