mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:17:44 +00:00
LibCore: Implement the 'X' modifier into FilePermissionMask
This commit is contained in:
parent
8598fbb008
commit
130f04c493
3 changed files with 48 additions and 8 deletions
|
@ -72,6 +72,16 @@ TEST_CASE(file_permission_mask_from_symbolic_notation)
|
||||||
EXPECT_EQ(mask.value().apply(0), 0555);
|
EXPECT_EQ(mask.value().apply(0), 0555);
|
||||||
EXPECT_EQ(mask.value().apply(0664), 0555);
|
EXPECT_EQ(mask.value().apply(0664), 0555);
|
||||||
|
|
||||||
|
mask = Core::FilePermissionsMask::from_symbolic_notation("a+X"sv);
|
||||||
|
EXPECT(!mask.is_error());
|
||||||
|
EXPECT_EQ(mask.value().clear_mask(), 0);
|
||||||
|
EXPECT_EQ(mask.value().write_mask(), 0);
|
||||||
|
EXPECT_EQ(mask.value().directory_or_executable_mask().clear_mask(), 0);
|
||||||
|
EXPECT_EQ(mask.value().directory_or_executable_mask().write_mask(), 0111);
|
||||||
|
EXPECT_EQ(mask.value().apply(0), 0);
|
||||||
|
EXPECT_EQ(mask.value().apply(0100), 0111);
|
||||||
|
EXPECT_EQ(mask.value().apply(S_IFDIR | 0), S_IFDIR | 0111);
|
||||||
|
|
||||||
mask = Core::FilePermissionsMask::from_symbolic_notation("z+rw"sv);
|
mask = Core::FilePermissionsMask::from_symbolic_notation("z+rw"sv);
|
||||||
EXPECT(mask.is_error());
|
EXPECT(mask.is_error());
|
||||||
EXPECT(mask.error().string_literal().starts_with("invalid class"sv));
|
EXPECT(mask.error().string_literal().starts_with("invalid class"sv));
|
||||||
|
|
|
@ -42,7 +42,7 @@ ErrorOr<FilePermissionsMask> FilePermissionsMask::from_numeric_notation(StringVi
|
||||||
mode_t mode = AK::StringUtils::convert_to_uint_from_octal<u16>(string).value_or(01000);
|
mode_t mode = AK::StringUtils::convert_to_uint_from_octal<u16>(string).value_or(01000);
|
||||||
if (mode > 0777)
|
if (mode > 0777)
|
||||||
return Error::from_string_literal("invalid octal representation");
|
return Error::from_string_literal("invalid octal representation");
|
||||||
return FilePermissionsMask().assign_permissions(mode);
|
return move(FilePermissionsMask().assign_permissions(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<FilePermissionsMask> FilePermissionsMask::from_symbolic_notation(StringView string)
|
ErrorOr<FilePermissionsMask> FilePermissionsMask::from_symbolic_notation(StringView string)
|
||||||
|
@ -98,25 +98,37 @@ ErrorOr<FilePermissionsMask> FilePermissionsMask::from_symbolic_notation(StringV
|
||||||
}
|
}
|
||||||
|
|
||||||
mode_t write_bits = 0;
|
mode_t write_bits = 0;
|
||||||
|
bool apply_to_directories_and_executables_only = false;
|
||||||
|
|
||||||
if (ch == 'r')
|
switch (ch) {
|
||||||
|
case 'r':
|
||||||
write_bits = 4;
|
write_bits = 4;
|
||||||
else if (ch == 'w')
|
break;
|
||||||
|
case 'w':
|
||||||
write_bits = 2;
|
write_bits = 2;
|
||||||
else if (ch == 'x')
|
break;
|
||||||
|
case 'x':
|
||||||
write_bits = 1;
|
write_bits = 1;
|
||||||
else
|
break;
|
||||||
|
case 'X':
|
||||||
|
write_bits = 1;
|
||||||
|
apply_to_directories_and_executables_only = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return Error::from_string_literal("invalid symbolic permission: expected 'r', 'w' or 'x'");
|
return Error::from_string_literal("invalid symbolic permission: expected 'r', 'w' or 'x'");
|
||||||
|
}
|
||||||
|
|
||||||
mode_t clear_bits = operation == Operation::Assign ? 7 : write_bits;
|
mode_t clear_bits = operation == Operation::Assign ? 7 : write_bits;
|
||||||
|
|
||||||
|
FilePermissionsMask& edit_mask = apply_to_directories_and_executables_only ? mask.directory_or_executable_mask() : mask;
|
||||||
|
|
||||||
// Update masks one class at a time in other, group, user order
|
// Update masks one class at a time in other, group, user order
|
||||||
for (auto cls = classes; cls != 0; cls >>= 1) {
|
for (auto cls = classes; cls != 0; cls >>= 1) {
|
||||||
if (cls & 1) {
|
if (cls & 1) {
|
||||||
if (operation == Operation::Add || operation == Operation::Assign)
|
if (operation == Operation::Add || operation == Operation::Assign)
|
||||||
mask.add_permissions(write_bits);
|
edit_mask.add_permissions(write_bits);
|
||||||
if (operation == Operation::Remove || operation == Operation::Assign)
|
if (operation == Operation::Remove || operation == Operation::Assign)
|
||||||
mask.remove_permissions(clear_bits);
|
edit_mask.remove_permissions(clear_bits);
|
||||||
}
|
}
|
||||||
write_bits <<= 3;
|
write_bits <<= 3;
|
||||||
clear_bits <<= 3;
|
clear_bits <<= 3;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Error.h>
|
#include <AK/Error.h>
|
||||||
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -28,13 +29,30 @@ public:
|
||||||
FilePermissionsMask& add_permissions(mode_t mode);
|
FilePermissionsMask& add_permissions(mode_t mode);
|
||||||
FilePermissionsMask& remove_permissions(mode_t mode);
|
FilePermissionsMask& remove_permissions(mode_t mode);
|
||||||
|
|
||||||
mode_t apply(mode_t mode) const { return m_write_mask | (mode & ~m_clear_mask); }
|
mode_t apply(mode_t mode) const
|
||||||
|
{
|
||||||
|
if (m_directory_or_executable_mask && (S_ISDIR(mode) || (mode & 0111) != 0))
|
||||||
|
mode = m_directory_or_executable_mask->apply(mode);
|
||||||
|
|
||||||
|
return m_write_mask | (mode & ~m_clear_mask);
|
||||||
|
}
|
||||||
mode_t clear_mask() const { return m_clear_mask; }
|
mode_t clear_mask() const { return m_clear_mask; }
|
||||||
mode_t write_mask() const { return m_write_mask; }
|
mode_t write_mask() const { return m_write_mask; }
|
||||||
|
|
||||||
|
FilePermissionsMask& directory_or_executable_mask()
|
||||||
|
{
|
||||||
|
if (!m_directory_or_executable_mask)
|
||||||
|
m_directory_or_executable_mask = make<FilePermissionsMask>();
|
||||||
|
|
||||||
|
return *m_directory_or_executable_mask;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mode_t m_clear_mask; // the bits that will be cleared
|
mode_t m_clear_mask; // the bits that will be cleared
|
||||||
mode_t m_write_mask; // the bits that will be set
|
mode_t m_write_mask; // the bits that will be set
|
||||||
|
|
||||||
|
// A separate mask, only for files that already have some executable bit set or directories.
|
||||||
|
OwnPtr<FilePermissionsMask> m_directory_or_executable_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue