Skip to content

Commit

Permalink
iox-eclipse-iceoryx#1560 Move filesystem-related methods from 'helple…
Browse files Browse the repository at this point in the history
…ts.hpp' to 'filesystem.hpp'

Signed-off-by: Simon Hoinkis <simon.hoinkis@apex.ai>
  • Loading branch information
mossmaurice committed Feb 1, 2023
1 parent 542a268 commit aa292b2
Show file tree
Hide file tree
Showing 7 changed files with 780 additions and 809 deletions.
68 changes: 68 additions & 0 deletions iceoryx_hoofs/include/iceoryx_hoofs/cxx/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,81 @@
#ifndef IOX_HOOFS_CXX_FILESYSTEM_HPP
#define IOX_HOOFS_CXX_FILESYSTEM_HPP

#include "iox/string.hpp"

#include <cstdint>
#include <type_traits>

namespace iox
{
namespace cxx
{
namespace internal
{
// AXIVION DISABLE STYLE AutosarC++19_03-A3.9.1: Not used as an integer but as actual character.
constexpr char ASCII_A{'a'};
constexpr char ASCII_Z{'z'};
constexpr char ASCII_CAPITAL_A{'A'};
constexpr char ASCII_CAPITAL_Z{'Z'};
constexpr char ASCII_0{'0'};
constexpr char ASCII_9{'9'};
constexpr char ASCII_MINUS{'-'};
constexpr char ASCII_DOT{'.'};
constexpr char ASCII_COLON{':'};
constexpr char ASCII_UNDERSCORE{'_'};
} // namespace internal
// AXIVION ENABLE STYLE AutosarC++19_03-A3.9.1

enum class RelativePathComponents : std::uint32_t
{
REJECT,
ACCEPT
};

/// @brief checks if the given string is a valid path entry. A path entry is the string between
/// two path separators.
/// @note A valid path entry for iceoryx must be platform independent and also supported
/// by various file systems. The file systems we intend to support are
/// * linux: ext3, ext4, btrfs
/// * windows: ntfs, exfat, fat
/// * freebsd: ufs, ffs
/// * apple: apfs
/// * qnx: etfs
/// * android: ext3, ext4, fat
///
/// Sometimes it is also possible that a certain file character is supported by the filesystem
/// itself but not by the platforms SDK. One example are files which end with a dot like "myFile."
/// which are supported by ntfs but not by the Windows SDK.
/// @param[in] name the path entry in question
/// @param[in] relativePathComponents are relative path components are allowed for this path entry
/// @return true if it is valid, otherwise false
template <uint64_t StringCapacity>
bool isValidPathEntry(const string<StringCapacity>& name, const RelativePathComponents relativePathComponents) noexcept;

/// @brief checks if the given string is a valid filename. It must fulfill the
/// requirements of a valid path entry (see, isValidPathEntry) and is not allowed
/// to contain relative path components
/// @param[in] name the string to verify
/// @return true if the string is a filename, otherwise false
template <uint64_t StringCapacity>
bool isValidFileName(const string<StringCapacity>& name) noexcept;

/// @brief verifies if the given string is a valid path to a file
/// @param[in] name the string to verify
/// @return true if the string is a path to a file, otherwise false
template <uint64_t StringCapacity>
bool isValidPathToFile(const string<StringCapacity>& name) noexcept;

/// @brief returns true if the provided name is a valid path, otherwise false
/// @param[in] name the string to verify
template <uint64_t StringCapacity>
bool isValidPathToDirectory(const string<StringCapacity>& name) noexcept;

/// @brief returns true if the provided name ends with a path separator, otherwise false
/// @param[in] name the string which may contain a path separator at the end
template <uint64_t StringCapacity>
bool doesEndWithPathSeparator(const string<StringCapacity>& name) noexcept;

/// @brief this enum class implements the filesystem perms feature of C++17. The
/// API is identical to the C++17 one so that the class can be removed
/// as soon as iceoryx switches to C++17.
Expand Down
68 changes: 0 additions & 68 deletions iceoryx_hoofs/include/iceoryx_hoofs/cxx/helplets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,6 @@ class string;
struct TruncateToCapacity_t;
namespace cxx
{
namespace internal
{
// AXIVION DISABLE STYLE AutosarC++19_03-A3.9.1: Not used as an integer but as actual character.
constexpr char ASCII_A{'a'};
constexpr char ASCII_Z{'z'};
constexpr char ASCII_CAPITAL_A{'A'};
constexpr char ASCII_CAPITAL_Z{'Z'};
constexpr char ASCII_0{'0'};
constexpr char ASCII_9{'9'};
constexpr char ASCII_MINUS{'-'};
constexpr char ASCII_DOT{'.'};
constexpr char ASCII_COLON{':'};
constexpr char ASCII_UNDERSCORE{'_'};
} // namespace internal
// AXIVION ENABLE STYLE AutosarC++19_03-A3.9.1

template <typename T, typename = typename std::enable_if<std::is_pointer<T>::value, void>::type>
struct not_null
{
Expand Down Expand Up @@ -98,59 +82,7 @@ constexpr bool isCompiledOn32BitSystem() noexcept
{
return INTPTR_MAX == INT32_MAX;
}

enum class RelativePathComponents : std::uint32_t
{
REJECT,
ACCEPT
};

/// @brief checks if the given string is a valid path entry. A path entry is the string between
/// two path separators.
/// @note A valid path entry for iceoryx must be platform independent and also supported
/// by various file systems. The file systems we intend to support are
/// * linux: ext3, ext4, btrfs
/// * windows: ntfs, exfat, fat
/// * freebsd: ufs, ffs
/// * apple: apfs
/// * qnx: etfs
/// * android: ext3, ext4, fat
///
/// Sometimes it is also possible that a certain file character is supported by the filesystem
/// itself but not by the platforms SDK. One example are files which end with a dot like "myFile."
/// which are supported by ntfs but not by the Windows SDK.
/// @param[in] name the path entry in question
/// @param[in] relativePathComponents are relative path components are allowed for this path entry
/// @return true if it is valid, otherwise false
template <uint64_t StringCapacity>
bool isValidPathEntry(const string<StringCapacity>& name, const RelativePathComponents relativePathComponents) noexcept;

/// @brief checks if the given string is a valid filename. It must fulfill the
/// requirements of a valid path entry (see, isValidPathEntry) and is not allowed
/// to contain relative path components
/// @param[in] name the string to verify
/// @return true if the string is a filename, otherwise false
template <uint64_t StringCapacity>
bool isValidFileName(const string<StringCapacity>& name) noexcept;

/// @brief verifies if the given string is a valid path to a file
/// @param[in] name the string to verify
/// @return true if the string is a path to a file, otherwise false
template <uint64_t StringCapacity>
bool isValidPathToFile(const string<StringCapacity>& name) noexcept;

/// @brief returns true if the provided name is a valid path, otherwise false
/// @param[in] name the string to verify
template <uint64_t StringCapacity>
bool isValidPathToDirectory(const string<StringCapacity>& name) noexcept;

/// @brief returns true if the provided name ends with a path separator, otherwise false
/// @param[in] name the string which may contain a path separator at the end
template <uint64_t StringCapacity>
bool doesEndWithPathSeparator(const string<StringCapacity>& name) noexcept;
} // namespace cxx
} // namespace iox

#include "iceoryx_hoofs/internal/cxx/helplets.inl"

#endif // IOX_HOOFS_CXX_HELPLETS_HPP
148 changes: 148 additions & 0 deletions iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/filesystem.inl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,154 @@ namespace iox
{
namespace cxx
{
template <uint64_t StringCapacity>
inline bool isValidPathEntry(const iox::string<StringCapacity>& name,
const RelativePathComponents relativePathComponents) noexcept
{
const iox::string<StringCapacity> currentDirectory{"."};
const iox::string<StringCapacity> parentDirectory{".."};

if ((name == currentDirectory) || (name == parentDirectory))
{
return relativePathComponents == RelativePathComponents::ACCEPT;
}

const auto nameSize = name.size();

for (uint64_t i{0}; i < nameSize; ++i)
{
// AXIVION Next Construct AutosarC++19_03-A3.9.1: Not used as an integer but as actual character
const char c{name[i]};

const bool isSmallLetter{(internal::ASCII_A <= c) && (c <= internal::ASCII_Z)};
const bool isCapitalLetter{(internal::ASCII_CAPITAL_A <= c) && (c <= internal::ASCII_CAPITAL_Z)};
const bool isNumber{(internal::ASCII_0 <= c) && (c <= internal::ASCII_9)};
const bool isSpecialCharacter{((c == internal::ASCII_MINUS) || (c == internal::ASCII_DOT))
|| ((c == internal::ASCII_COLON) || (c == internal::ASCII_UNDERSCORE))};

if ((!isSmallLetter && !isCapitalLetter) && (!isNumber && !isSpecialCharacter))
{
return false;
}
}

if (nameSize == 0)
{
return true;
}

// dot at the end is invalid to be compatible with windows api
return !(name[nameSize - 1] == '.');
}

template <uint64_t StringCapacity>
inline bool isValidFileName(const iox::string<StringCapacity>& name) noexcept
{
if (name.empty())
{
return false;
}

// check if the file contains only valid characters
return isValidPathEntry(name, RelativePathComponents::REJECT);
}

template <uint64_t StringCapacity>
inline bool isValidPathToFile(const iox::string<StringCapacity>& name) noexcept
{
if (doesEndWithPathSeparator(name))
{
return false;
}

iox::string<StringCapacity> filePart{name};
iox::string<StringCapacity> pathPart;

name.find_last_of(iox::string<platform::IOX_NUMBER_OF_PATH_SEPARATORS>(TruncateToCapacity,
&platform::IOX_PATH_SEPARATORS[0],
platform::IOX_NUMBER_OF_PATH_SEPARATORS))
.and_then([&](auto position) {
name.substr(position + 1).and_then([&filePart](auto& s) { filePart = s; });
name.substr(0, position).and_then([&pathPart](auto& s) { pathPart = s; });
});

return (pathPart.empty() || isValidPathToDirectory(pathPart)) && isValidFileName(filePart);
}

template <uint64_t StringCapacity>
inline bool isValidPathToDirectory(const iox::string<StringCapacity>& name) noexcept
{
if (name.empty())
{
return false;
}

auto temp = name;

const iox::string<StringCapacity> currentDirectory{"."};
const iox::string<StringCapacity> parentDirectory{".."};

while (!temp.empty())
{
auto separatorPosition = temp.find_first_of(iox::string<platform::IOX_NUMBER_OF_PATH_SEPARATORS>(
TruncateToCapacity, &platform::IOX_PATH_SEPARATORS[0], platform::IOX_NUMBER_OF_PATH_SEPARATORS));

// multiple slashes are explicitly allowed. the following paths
// are equivalent:
// /some/fuu/bar
// //some///fuu////bar
if (separatorPosition && (*separatorPosition == 0))
{
temp.substr(*separatorPosition + 1).and_then([&temp](auto& s) { temp = s; });
continue;
}

// verify if the entry between two path separators is a valid directory
// name, e.g. either it has the relative component . or .. or conforms
// with a valid file name
if (separatorPosition)
{
auto filenameToVerify = temp.substr(0, *separatorPosition);
bool isValidDirectory{
(isValidFileName(*filenameToVerify))
|| ((*filenameToVerify == currentDirectory) || (*filenameToVerify == parentDirectory))};
if (!isValidDirectory)
{
return false;
}

temp.substr(*separatorPosition + 1).and_then([&temp](auto& s) { temp = s; });
}
// we reached the last entry, if its a valid file name the path is valid
else
{
return isValidPathEntry(temp, RelativePathComponents::ACCEPT);
}
}

return true;
}

template <uint64_t StringCapacity>
inline bool doesEndWithPathSeparator(const iox::string<StringCapacity>& name) noexcept
{
if (name.empty())
{
return false;
}
// AXIVION Next Construct AutosarC++19_03-A3.9.1: Not used as an integer but as actual character
char lastCharacter{name[name.size() - 1U]};

for (const auto separator : iox::platform::IOX_PATH_SEPARATORS)
{
if (lastCharacter == separator)
{
return true;
}
}
return false;
}

constexpr perms operator|(const perms lhs, const perms rhs) noexcept
{
using T = std::underlying_type<perms>::type;
Expand Down
Loading

0 comments on commit aa292b2

Please sign in to comment.