From 7bbdee6cc402253a43f94b38f071a4ce794179f3 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 2 Jun 2023 11:43:46 +0300 Subject: [PATCH] Kernel: Symlinks are now working We still have to implement loop or depth detection --- kernel/include/kernel/FS/VirtualFileSystem.h | 4 +- kernel/kernel/FS/VirtualFileSystem.cpp | 69 +++++++++++++------- kernel/kernel/Process.cpp | 4 +- kernel/kernel/Shell.cpp | 1 + 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index c2e815d2..a97586e3 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -25,7 +25,7 @@ namespace Kernel BAN::RefPtr inode; BAN::String canonical_path; }; - BAN::ErrorOr file_from_absolute_path(BAN::StringView, bool follow_links); + BAN::ErrorOr file_from_absolute_path(BAN::StringView, bool follow_link); private: VirtualFileSystem() = default; @@ -39,7 +39,7 @@ namespace Kernel MountPoint* mount_from_root_inode(BAN::RefPtr); private: - RecursiveSpinLock m_lock; + SpinLock m_lock; FileSystem* m_root_fs = nullptr; BAN::Vector m_mount_points; }; diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index e4b85242..86bcbb2f 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -82,7 +82,7 @@ namespace Kernel return nullptr; } - BAN::ErrorOr VirtualFileSystem::file_from_absolute_path(BAN::StringView path, bool follow_links) + BAN::ErrorOr VirtualFileSystem::file_from_absolute_path(BAN::StringView path, bool follow_link) { LockGuard _(m_lock); @@ -93,13 +93,22 @@ namespace Kernel BAN::String canonical_path; - const auto path_parts = TRY(path.split('/')); + BAN::Vector path_parts; - for (auto path_part : path_parts) { + auto temp = TRY(path.split('/')); + for (size_t i = 0; i < temp.size(); i++) + TRY(path_parts.push_back(temp[temp.size() - i - 1])); + } + + while (!path_parts.empty()) + { + const auto& path_part = path_parts.back(); + auto orig = inode; + if (path_part.empty() || path_part == "."sv) { - continue; + } else if (path_part == ".."sv) { @@ -119,32 +128,42 @@ namespace Kernel else { inode = TRY(inode->read_directory_inode(path_part)); - TRY(canonical_path.push_back('/')); - TRY(canonical_path.append(path_part)); if (auto* mount_point = mount_from_host_inode(inode)) inode = mount_point->target->root_inode(); - if (follow_links && inode->mode().iflnk()) + TRY(canonical_path.push_back('/')); + TRY(canonical_path.append(path_part)); + } + + path_parts.pop_back(); + + if (inode->mode().iflnk() && (follow_link || !path_parts.empty())) + { + auto target = TRY(inode->link_target()); + if (target.empty()) + return BAN::Error::from_errno(ENOENT); + + if (target.front() == '/') { - auto target = TRY(inode->link_target()); - if (target.empty()) - return BAN::Error::from_errno(ENOENT); - if (target.front() == '/') - { - File file = TRY(file_from_absolute_path(target, follow_links)); - inode = file.inode; - canonical_path = BAN::move(file.canonical_path); - } - else - { - while (canonical_path.back() != '/') - canonical_path.pop_back(); - TRY(canonical_path.append(target)); - File file = TRY(file_from_absolute_path(canonical_path, follow_links)); - inode = file.inode; - canonical_path = BAN::move(file.canonical_path); - } + inode = root_inode(); + canonical_path.clear(); + + auto temp = TRY(target.sv().split('/')); + for (size_t i = 0; i < temp.size(); i++) + TRY(path_parts.emplace_back(temp[temp.size() - i - 1])); + } + else + { + inode = orig; + + while (canonical_path.back() != '/') + canonical_path.pop_back(); + canonical_path.pop_back(); + + auto new_parts = TRY(target.sv().split('/')); + for (size_t i = 0; i < new_parts.size(); i++) + TRY(path_parts.emplace_back(new_parts[new_parts.size() - i - 1])); } } } diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 1f2060ae..2a88dc11 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -296,7 +296,7 @@ namespace Kernel BAN::ErrorOr Process::open(BAN::StringView path, int flags) { - if (flags & ~O_RDWR) + if (flags & ~(O_RDONLY | O_WRONLY | O_NOFOLLOW)) return BAN::Error::from_errno(ENOTSUP); BAN::String absolute_path = TRY(absolute_path_of(path)); @@ -468,7 +468,7 @@ namespace Kernel BAN::ErrorOr Process::stat(BAN::StringView path, struct stat* out) { - int fd = TRY(open(path, O_RDONLY)); + int fd = TRY(open(path, O_RDONLY | O_NOFOLLOW)); auto ret = fstat(fd, out); MUST(close(fd)); return ret; diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 78a926a2..5e8a3e39 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -41,6 +41,7 @@ namespace Kernel mode.ifdir() ? 'd' : mode.ifblk() ? 'b' : mode.ifchr() ? 'c' : + mode.iflnk() ? 'l' : '-'; buffer[1] = (mode.mode & Inode::Mode::IRUSR) ? 'r' : '-';