From 87a62f4def45da6d03bd7e60d8a0090c76143753 Mon Sep 17 00:00:00 2001 From: Max Wipfli Date: Tue, 6 Jul 2021 11:16:17 +0200 Subject: [PATCH] Kernel: Add KLexicalPath This adds KLexicalPath, which are a few static functions which aim to mostly emulate AK::LexicalPath. They are however constrained to work with absolute paths only, containing no '.' or '..' path segments and no consecutive slashes. This way, it is possible to avoid use StringView for the return values and thus avoid allocating new String objects. As explained above, the functions are currently very strict about the allowed input paths. This seems to not be a problem currently. Since the functions VERIFY this, potential bugs caused by this will become immediately obvious. --- Kernel/CMakeLists.txt | 1 + Kernel/KLexicalPath.cpp | 58 +++++++++++++++++++++++++++++++++++++++++ Kernel/KLexicalPath.h | 19 ++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 Kernel/KLexicalPath.cpp create mode 100644 Kernel/KLexicalPath.h diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index dbaebcb06d..ecd2c37a20 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -128,6 +128,7 @@ set(KERNEL_SOURCES Interrupts/SpuriousInterruptHandler.cpp Interrupts/UnhandledInterruptHandler.cpp KBufferBuilder.cpp + KLexicalPath.cpp KString.cpp KSyms.cpp Lock.cpp diff --git a/Kernel/KLexicalPath.cpp b/Kernel/KLexicalPath.cpp new file mode 100644 index 0000000000..8e9cc34c98 --- /dev/null +++ b/Kernel/KLexicalPath.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021, Max Wipfli + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Kernel::KLexicalPath { + +bool is_absolute(StringView const& path) +{ + return !path.is_empty() && path[0] == '/'; +} + +bool is_canonical(StringView const& path) +{ + // FIXME: This can probably be done more efficiently. + if (path.is_empty()) + return false; + if (path.ends_with('/') && path.length() != 1) + return false; + if (path.starts_with("./"sv) || path.contains("/./"sv) || path.ends_with("/."sv)) + return false; + if (path.starts_with("../"sv) || path.contains("/../"sv) || path.ends_with("/..")) + return false; + if (path.contains("//"sv)) + return false; + return true; +} + +StringView basename(StringView const& path) +{ + auto slash_index = path.find_last('/'); + if (!slash_index.has_value()) { + VERIFY(!path.is_empty()); + return path; + } + auto basename = path.substring_view(*slash_index + 1); + VERIFY(!basename.is_empty() && basename != "."sv && basename != ".."sv); + return basename; +} + +StringView dirname(StringView const& path) +{ + VERIFY(is_canonical(path)); + auto slash_index = path.find_last('/'); + VERIFY(slash_index.has_value()); + return path.substring_view(0, *slash_index); +} + +Vector parts(StringView const& path) +{ + VERIFY(is_canonical(path)); + return path.split_view('/'); +} + +} diff --git a/Kernel/KLexicalPath.h b/Kernel/KLexicalPath.h new file mode 100644 index 0000000000..87b7bea87a --- /dev/null +++ b/Kernel/KLexicalPath.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, Max Wipfli + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Kernel::KLexicalPath { + +bool is_absolute(StringView const&); +bool is_canonical(StringView const&); +StringView basename(StringView const&); +StringView dirname(StringView const&); +Vector parts(StringView const&); + +}