LibCore: Restore support for multiple symbolic classes

Reverts recent change introduced to support implicit symbolic permission
which broke the parser when multiple classes are specified.
The state machine must assume it's dealing with classes until an
operation character is consumed.
This commit is contained in:
Xavier Defrang 2022-01-11 17:15:21 +01:00 committed by Brian Gianforcaro
parent c839ff574a
commit 30f58de800
Notes: sideshowbarker 2024-07-17 20:19:59 +09:00
2 changed files with 44 additions and 34 deletions

View file

@ -44,6 +44,13 @@ TEST_CASE(file_permission_mask_from_symbolic_notation)
EXPECT_EQ(mask.value().apply(0), 0555);
EXPECT_EQ(mask.value().apply(0664), 0555);
mask = Core::FilePermissionsMask::from_symbolic_notation("ugo=rx"sv);
EXPECT(!mask.is_error());
EXPECT_EQ(mask.value().clear_mask(), 0777);
EXPECT_EQ(mask.value().write_mask(), 0555);
EXPECT_EQ(mask.value().apply(0), 0555);
EXPECT_EQ(mask.value().apply(0664), 0555);
mask = Core::FilePermissionsMask::from_symbolic_notation("u+rw,g=rx,o-rwx"sv);
EXPECT(!mask.is_error());
EXPECT_EQ(mask.value().clear_mask(), 0077);
@ -51,6 +58,20 @@ TEST_CASE(file_permission_mask_from_symbolic_notation)
EXPECT_EQ(mask.value().apply(0), 0650);
EXPECT_EQ(mask.value().apply(0177), 0750);
mask = Core::FilePermissionsMask::from_symbolic_notation("+r"sv);
EXPECT(!mask.is_error());
EXPECT_EQ(mask.value().clear_mask(), 0);
EXPECT_EQ(mask.value().write_mask(), 0444);
EXPECT_EQ(mask.value().apply(0), 0444);
EXPECT_EQ(mask.value().apply(0123), 0567);
mask = Core::FilePermissionsMask::from_symbolic_notation("=rx"sv);
EXPECT(!mask.is_error());
EXPECT_EQ(mask.value().clear_mask(), 0777);
EXPECT_EQ(mask.value().write_mask(), 0555);
EXPECT_EQ(mask.value().apply(0), 0555);
EXPECT_EQ(mask.value().apply(0664), 0555);
mask = Core::FilePermissionsMask::from_symbolic_notation("z+rw"sv);
EXPECT(mask.is_error());

View file

@ -14,14 +14,14 @@ namespace Core {
enum State {
Classes,
Operation,
Mode
};
enum ClassFlag {
Other = 1,
Group = 2,
User = 4
User = 4,
All = 7
};
enum Operation {
@ -56,43 +56,32 @@ ErrorOr<FilePermissionsMask> FilePermissionsMask::from_symbolic_notation(StringV
for (auto ch : string) {
switch (state) {
case State::Classes: {
// one or more [ugoa] terminated by one operator [+-=]
if (ch == 'u') {
// zero or more [ugoa] terminated by one operator [+-=]
if (ch == 'u')
classes |= ClassFlag::User;
state = State::Operation;
break;
} else if (ch == 'g') {
else if (ch == 'g')
classes |= ClassFlag::Group;
state = State::Operation;
break;
} else if (ch == 'o') {
else if (ch == 'o')
classes |= ClassFlag::Other;
state = State::Operation;
break;
} else if (ch == 'a') {
classes = ClassFlag::User | ClassFlag::Group | ClassFlag::Other;
state = State::Operation;
break;
else if (ch == 'a')
classes = ClassFlag::All;
else {
if (ch == '+')
operation = Operation::Add;
else if (ch == '-')
operation = Operation::Remove;
else if (ch == '=')
operation = Operation::Assign;
else
return Error::from_string_literal("invalid operation: expected '+', '-' or '='"sv);
// if an operation was specified without a class, assume all
if (classes == 0)
classes = ClassFlag::All;
state = State::Mode;
}
}
[[fallthrough]];
case State::Operation: {
if (ch == '+')
operation = Operation::Add;
else if (ch == '-')
operation = Operation::Remove;
else if (ch == '=')
operation = Operation::Assign;
else if (classes == 0)
return Error::from_string_literal("invalid access class: expected 'u', 'g', 'o' or 'a' "sv);
else
return Error::from_string_literal("invalid operation: expected '+', '-' or '='"sv);
// if an operation was specified without a class, assume all
if (classes == 0)
classes = ClassFlag::User | ClassFlag::Group | ClassFlag::Other;
state = State::Mode;
break;
}