Skip to content

Commit

Permalink
Kernel: Add KLexicalPath
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
MaxWipfli authored and awesomekling committed Jul 7, 2021
1 parent 75ba74a commit 87a62f4
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions Kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ set(KERNEL_SOURCES
Interrupts/SpuriousInterruptHandler.cpp
Interrupts/UnhandledInterruptHandler.cpp
KBufferBuilder.cpp
KLexicalPath.cpp
KString.cpp
KSyms.cpp
Lock.cpp
Expand Down
58 changes: 58 additions & 0 deletions Kernel/KLexicalPath.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2021, Max Wipfli <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <Kernel/KLexicalPath.h>

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<StringView> parts(StringView const& path)
{
VERIFY(is_canonical(path));
return path.split_view('/');
}

}
19 changes: 19 additions & 0 deletions Kernel/KLexicalPath.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2021, Max Wipfli <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <AK/StringView.h>

namespace Kernel::KLexicalPath {

bool is_absolute(StringView const&);
bool is_canonical(StringView const&);
StringView basename(StringView const&);
StringView dirname(StringView const&);
Vector<StringView> parts(StringView const&);

}

0 comments on commit 87a62f4

Please sign in to comment.