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&); + +}