diff --git a/Tests/LibCore/TestLibCoreFilePermissionsMask.cpp b/Tests/LibCore/TestLibCoreFilePermissionsMask.cpp index 1dc303c0c6..55f300be5f 100644 --- a/Tests/LibCore/TestLibCoreFilePermissionsMask.cpp +++ b/Tests/LibCore/TestLibCoreFilePermissionsMask.cpp @@ -116,3 +116,24 @@ TEST_CASE(file_permission_mask_parse) mask = Core::FilePermissionsMask::parse("z+rw"sv); EXPECT(mask.is_error()); } + +TEST_CASE(numeric_mask_special_bits) +{ + { + auto mask = Core::FilePermissionsMask::parse("750"sv); + EXPECT(!mask.is_error()); + EXPECT_EQ(mask.value().apply(07000), 07750); + } + + { + auto mask = Core::FilePermissionsMask::parse("7750"sv); + EXPECT(!mask.is_error()); + EXPECT_EQ(mask.value().apply(0), 07750); + } + + { + auto mask = Core::FilePermissionsMask::parse("0750"sv); + EXPECT(!mask.is_error()); + EXPECT_EQ(mask.value().apply(07000), 0750); + } +} diff --git a/Userland/Libraries/LibCore/FilePermissionsMask.cpp b/Userland/Libraries/LibCore/FilePermissionsMask.cpp index bbb674ad01..c5e8d45fdf 100644 --- a/Userland/Libraries/LibCore/FilePermissionsMask.cpp +++ b/Userland/Libraries/LibCore/FilePermissionsMask.cpp @@ -39,10 +39,19 @@ ErrorOr FilePermissionsMask::parse(StringView string) ErrorOr FilePermissionsMask::from_numeric_notation(StringView string) { - mode_t mode = AK::StringUtils::convert_to_uint_from_octal(string).value_or(01000); - if (mode > 0777) + string = string.trim_whitespace(); + mode_t mode = AK::StringUtils::convert_to_uint_from_octal(string, TrimWhitespace::No).value_or(010000); + if (mode > 07777) return Error::from_string_literal("invalid octal representation"); - return move(FilePermissionsMask().assign_permissions(mode)); + + FilePermissionsMask mask; + mask.assign_permissions(mode); + + // For compatibility purposes, just clear the special mode bits if we explicitly passed a 4-character mode. + if (string.length() >= 4) + mask.remove_permissions(07000); + + return mask; } ErrorOr FilePermissionsMask::from_symbolic_notation(StringView string)