diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2024-10-02 08:30:08 -0500 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2024-10-02 08:30:08 -0500 |
commit | 2cdb2cac44a07fa5db72408f62427a64f32c1d90 (patch) | |
tree | 0795220193a293a0297fe16fc257507c41e78760 /include | |
parent | 3a18a6dcab45467e779e91c7b346aa3b148e8b9c (diff) |
Add permissions model for files.
Diffstat (limited to 'include')
-rw-r--r-- | include/fud_c_file.hpp | 44 | ||||
-rw-r--r-- | include/fud_permissions.hpp | 191 |
2 files changed, 234 insertions, 1 deletions
diff --git a/include/fud_c_file.hpp b/include/fud_c_file.hpp index 45a8b54..f451292 100644 --- a/include/fud_c_file.hpp +++ b/include/fud_c_file.hpp @@ -21,9 +21,13 @@ #include "fud_result.hpp" #include "fud_status.hpp" #include "fud_string.hpp" +#include "fud_permissions.hpp" #include <cstdint> #include <cstdio> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> namespace fud { @@ -109,6 +113,27 @@ class CFile { return self.m_file != nullptr ? FudStatus::Success : FudStatus::Failure; } + FudStatus create(Permissions permissions) + { + auto& self = static_cast<Derived&>(*this); + if (self.m_modeFlags == CFileMode::ReadOnly || self.m_modeFlags == CFileMode::ReadWrite) { + return FudStatus::OperationInvalid; + } + + if (!self.m_filename.valid()) { + return FudStatus::ObjectInvalid; + } + + auto fdResult = ::open(self.m_filename.c_str(), O_CREAT, permissions.mode()); + if (fdResult == -1) { + return FudStatus::Failure; + } + ::close(fdResult); + + self.m_file = fopen(self.m_filename.c_str(), self.m_mode.c_str()); + return self.m_file != nullptr ? FudStatus::Success : FudStatus::Failure; + } + void close() { auto& self = static_cast<Derived&>(*this); @@ -130,6 +155,22 @@ class CFile { return self.m_file; } + FudStatus setPermissions(Permissions permissions) { + auto& self = static_cast<Derived&>(*this); + if (!self.isOpen()) { + return FudStatus::OperationInvalid; + } + auto descriptor = fileno(self.file()); + if (descriptor == -1) { + return FudStatus::ObjectInvalid; + } + auto result = fchmod(descriptor, permissions()); + if (result != 0) { + return FudStatus::Failure; + } + return FudStatus::Success; + } + [[nodiscard]] Result<size_t, FudStatus> size() const { const auto& self = static_cast<const Derived&>(*this); @@ -311,7 +352,8 @@ class CFile { auto& self = static_cast<Derived&>(*this); return self.write(static_cast<const void*>(&source), sourceSize, length, offset); } -private: + + private: FudStatus reset() const { const auto& self = static_cast<const Derived&>(*this); diff --git a/include/fud_permissions.hpp b/include/fud_permissions.hpp new file mode 100644 index 0000000..66eec0c --- /dev/null +++ b/include/fud_permissions.hpp @@ -0,0 +1,191 @@ +/* + * libfud + * Copyright 2024 Dominick Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FUD_PERMISSIONS_HPP +#define FUD_PERMISSIONS_HPP + +#include <climits> +#include <cstdint> +#include <sys/stat.h> +#include <type_traits> + +namespace fud { + +static_assert(CHAR_BIT == 8, "Assume that uint8_t has 8 bits"); +static_assert(sizeof(uint8_t) == 1, "Assume that uint8_t is 1 byte"); + +enum class PermissionType : uint8_t +{ + None = 0x00, + Exec = 0x01, + Write = 0x02, + Read = 0x04 +}; + +struct PermissionField { + explicit constexpr PermissionField(PermissionType permissionType) : + m_permissions{static_cast<uint8_t>(permissionType)} + { + } + + constexpr PermissionField(PermissionType lhs, PermissionType rhs) + { + m_permissions = static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs); + } + + constexpr PermissionField(PermissionType lhs, PermissionField rhs) + { + m_permissions = static_cast<uint8_t>(lhs) | rhs.m_permissions; + } + + constexpr PermissionField(PermissionField lhs, PermissionType rhs) + { + m_permissions = lhs.m_permissions | static_cast<uint8_t>(rhs); + } + + constexpr PermissionField(PermissionField lhs, PermissionField rhs) + { + m_permissions = lhs.m_permissions | rhs.m_permissions; + } + + constexpr uint16_t operator()() + { + return m_permissions; + } + + uint8_t m_permissions{}; +}; + +enum class PermissionSpecialType : uint8_t +{ + None = 0x00, + Sticky = 0x01, + SetGroupId = 0x02, + SetUserId = 0x04 +}; + +struct PermissionSpecial { + explicit constexpr PermissionSpecial(PermissionSpecialType permissionType) : + m_permissions{static_cast<uint8_t>(permissionType)} + { + } + + constexpr PermissionSpecial(PermissionSpecialType lhs, PermissionSpecialType rhs) + { + m_permissions = static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs); + } + + constexpr PermissionSpecial(PermissionSpecialType lhs, PermissionSpecial rhs) + { + m_permissions = static_cast<uint8_t>(lhs) | rhs.m_permissions; + } + + constexpr PermissionSpecial(PermissionSpecial lhs, PermissionSpecialType rhs) + { + m_permissions = lhs.m_permissions | static_cast<uint8_t>(rhs); + } + + constexpr PermissionSpecial(PermissionSpecial lhs, PermissionSpecial rhs) + { + m_permissions = lhs.m_permissions | rhs.m_permissions; + } + + constexpr uint16_t operator()() + { + return m_permissions; + } + + uint8_t m_permissions{0}; +}; + +class Permissions { + public: + static constexpr uint8_t GroupShift = 3; + static constexpr uint8_t UserShift = GroupShift + 3; + static constexpr uint8_t SpecialShift = UserShift + 3; + + constexpr Permissions(PermissionField user, PermissionField group, PermissionField others) + { + m_permissions = user() << UserShift | group() << GroupShift | others(); + } + + template <typename U, typename G, typename O> + constexpr Permissions(U user, G group, O others) + { + m_permissions = PermissionField{user}() << UserShift | PermissionField{group}() << GroupShift | + PermissionField{others}(); + } + + constexpr Permissions( + PermissionField user, + PermissionField group, + PermissionField others, + PermissionSpecial special) + { + m_permissions = special() << SpecialShift | user() << UserShift | group() << GroupShift | others(); + } + + template <typename U, typename G, typename O, typename S> + constexpr Permissions( + PermissionField user, + PermissionField group, + PermissionField others, + PermissionSpecial special) + { + m_permissions = special() << SpecialShift | PermissionField{user}() << UserShift | + PermissionField{group}() << GroupShift | PermissionField{others}(); + } + + constexpr int32_t operator()() + { + return m_permissions; + } + + constexpr mode_t mode() + { + return static_cast<mode_t>(m_permissions); + } + + private: + int32_t m_permissions{0}; +}; + +constexpr PermissionField operator|(PermissionType lhs, PermissionType rhs) +{ + return PermissionField{lhs, rhs}; +} + +constexpr PermissionField operator|(PermissionType lhs, PermissionField rhs) +{ + return PermissionField{lhs, rhs}; +} + +constexpr PermissionField operator|(PermissionField lhs, PermissionType rhs) +{ + return PermissionField{lhs, rhs}; +} + +constexpr PermissionField operator|(PermissionField lhs, PermissionField rhs) +{ + return PermissionField{lhs, rhs}; +} + +constexpr PermissionField PermReadWrite = PermissionType::Read | PermissionType::Write; + +} // namespace fud + +#endif |