diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index e04de87fea..89a747304d 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include InlineLinkedList& all_inodes() { @@ -56,6 +58,23 @@ ByteBuffer Inode::read_entire(FileDescription* descriptor) const return builder.to_byte_buffer(); } +KResultOr> Inode::resolve_as_link(Custody& base, RefPtr* out_parent, int options, int symlink_recursion_level) const +{ + // The default implementation simply treats the stored + // contents as a path and resolves that. That is, it + // behaves exactly how you would expect a symlink to work. + auto contents = read_entire(); + + if (!contents) { + if (out_parent) + *out_parent = nullptr; + return KResult(-ENOENT); + } + + auto path = StringView(contents.data(), contents.size()); + return VFS::the().resolve_path(path, base, out_parent, options, symlink_recursion_level); +} + unsigned Inode::fsid() const { return m_fs.fsid(); diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h index 5f25eae2ca..adaf01dc7c 100644 --- a/Kernel/FileSystem/Inode.h +++ b/Kernel/FileSystem/Inode.h @@ -15,6 +15,7 @@ class FileDescription; class InodeVMObject; class InodeWatcher; class LocalSocket; +class Custody; class Inode : public RefCounted , public Weakable @@ -53,6 +54,7 @@ public: virtual KResult chmod(mode_t) = 0; virtual KResult chown(uid_t, gid_t) = 0; virtual KResult truncate(off_t) { return KSuccess; } + virtual KResultOr> resolve_as_link(Custody& base, RefPtr* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0) const; LocalSocket* socket() { return m_socket.ptr(); } const LocalSocket* socket() const { return m_socket.ptr(); } diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index a4a4951706..a9703fd6fb 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -741,16 +741,7 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba if (options & O_NOFOLLOW_NOERROR) break; } - auto symlink_contents = child_inode->read_entire(); - if (!symlink_contents) { - if (out_parent) - *out_parent = nullptr; - return KResult(-ENOENT); - } - - auto symlink_path = StringView(symlink_contents.data(), symlink_contents.size()); - auto symlink_target = resolve_path(symlink_path, parent, out_parent, options, symlink_recursion_level + 1); - + auto symlink_target = child_inode->resolve_as_link(parent, out_parent, options, symlink_recursion_level + 1); if (symlink_target.is_error() || !have_more_parts) return symlink_target;