1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 08:07:44 +00:00

LibCore: Parse classless symbolic notation

This commit is contained in:
Jean-Baptiste Boric 2022-01-21 19:32:35 +01:00 committed by Andreas Kling
parent 736af8c7da
commit 12a6ec9292

View file

@ -13,7 +13,8 @@
namespace Core { namespace Core {
enum State { enum State {
Reference, Classes,
Operation,
Mode Mode
}; };
@ -48,47 +49,59 @@ ErrorOr<FilePermissionsMask> FilePermissionsMask::from_symbolic_notation(StringV
{ {
auto mask = FilePermissionsMask(); auto mask = FilePermissionsMask();
u8 state = State::Reference; u8 state = State::Classes;
u8 classes = 0; u8 classes = 0;
u8 operation = 0; u8 operation = 0;
for (auto ch : string) { for (auto ch : string) {
switch (state) { switch (state) {
case State::Reference: { case State::Classes: {
// one or more [ugoa] terminated by one operator [+-=] // one or more [ugoa] terminated by one operator [+-=]
if (ch == 'u') if (ch == 'u') {
classes |= ClassFlag::User; classes |= ClassFlag::User;
else if (ch == 'g') state = State::Operation;
break;
} else if (ch == 'g') {
classes |= ClassFlag::Group; classes |= ClassFlag::Group;
else if (ch == 'o') state = State::Operation;
break;
} else if (ch == 'o') {
classes |= ClassFlag::Other; classes |= ClassFlag::Other;
else if (ch == 'a') state = State::Operation;
break;
} else if (ch == 'a') {
classes = ClassFlag::User | ClassFlag::Group | ClassFlag::Other; classes = ClassFlag::User | ClassFlag::Group | ClassFlag::Other;
else { state = State::Operation;
if (classes == 0) break;
return Error::from_string_literal("invalid access class: expected 'u', 'g', 'o' or 'a' "sv);
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);
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; break;
} }
case State::Mode: { case State::Mode: {
// one or more [rwx] terminated by a comma // one or more [rwx] terminated by a comma
// End of mode part, expect reference next // End of mode part, expect class next
if (ch == ',') { if (ch == ',') {
state = State::Reference; state = State::Classes;
classes = operation = 0; classes = operation = 0;
continue; continue;
} }