summaryrefslogtreecommitdiff
path: root/Userland/Utilities
diff options
context:
space:
mode:
authorXavier Defrang <xavier.defrang@gmail.com>2021-12-25 11:02:56 +0100
committerBrian Gianforcaro <b.gianfo@gmail.com>2022-01-01 17:33:43 +0000
commit005b0f73849e3f9b4d0a0c069bf70caaea102e84 (patch)
tree92997b4ef63941d4d5c8a790811fdf455457e07f /Userland/Utilities
parent8b95423b5027e3363a3d7fc5e796bc4bf8a0ea15 (diff)
downloadserenity-005b0f73849e3f9b4d0a0c069bf70caaea102e84.zip
chmod: Use FilePermissionsMask to handle mode argument
Diffstat (limited to 'Userland/Utilities')
-rw-r--r--Userland/Utilities/chmod.cpp218
1 files changed, 6 insertions, 212 deletions
diff --git a/Userland/Utilities/chmod.cpp b/Userland/Utilities/chmod.cpp
index bed9f0d16d..f73f5caa7f 100644
--- a/Userland/Utilities/chmod.cpp
+++ b/Userland/Utilities/chmod.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Kenneth Myhra <kennethmyhra@gmail.com>
+ * Copyright (c) 2021, Xavier Defrang <xavier.defrang@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -10,61 +11,16 @@
#include <AK/String.h>
#include <AK/StringUtils.h>
#include <AK/Vector.h>
+#include <LibCore/FilePermissionsMask.h>
#include <LibCore/System.h>
#include <LibMain/Main.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
-/* the new mode will be computed using the boolean function(for each bit):
-
- |current mode|removal mask|applying mask|result |
- | 0 | 0 | 0 | 0 |
- | 0 | 0 | 1 | 1 |
- | 0 | 1 | 0 | 0 |
- | 0 | 1 | 1 | 1 | ---> find the CNF --> find the minimal CNF
- | 1 | 0 | 0 | 1 |
- | 1 | 0 | 1 | 1 |
- | 1 | 1 | 0 | 0 |
- | 1 | 1 | 1 | 1 |
-*/
-
-class Mask {
-private:
- mode_t removal_mask; // the bits that will be removed
- mode_t applying_mask; // the bits that will be set
-
-public:
- Mask()
- : removal_mask(0)
- , applying_mask(0)
- {
- }
-
- Mask& operator|=(const Mask& other)
- {
- removal_mask |= other.removal_mask;
- applying_mask |= other.applying_mask;
-
- return *this;
- }
-
- mode_t& get_removal_mask() { return removal_mask; }
- mode_t& get_applying_mask() { return applying_mask; }
-
- void set_mode(mode_t mode)
- {
- this->applying_mask = mode;
- this->removal_mask = ~mode;
- }
-};
-
-Optional<Mask> string_to_mode(char access_scope, StringView access_string);
-Optional<Mask> apply_permission(char access_scope, char permission, char operation);
-
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
- TRY(Core::System::pledge("stdio rpath fattr", nullptr));
+ TRY(Core::System::pledge("stdio rpath fattr"));
if (arguments.strings.size() < 3) {
warnln("usage: chmod <octal-mode> <path...>");
@@ -72,174 +28,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
return 1;
}
- Mask mask;
+ auto mask = TRY(Core::FilePermissionsMask::parse(arguments.strings[1]));
- /* compute a mask */
-
- auto mode_string = arguments.strings[1];
- if (mode_string[0] >= '0' && mode_string[0] <= '7') {
- mode_t mode = AK::StringUtils::convert_to_uint_from_octal<u16>(mode_string).value_or(01000);
- if (mode > 0777) {
- warnln("chmod: invalid mode: {}", mode_string);
- return 1;
- }
- mask.set_mode(mode);
- } else {
- auto access_strings = arguments.strings[1].split_view(',');
- for (auto access_string : access_strings) {
- Optional<Mask> tmp_mask;
- switch (access_string[0]) {
- case 'u':
- tmp_mask = string_to_mode('u', access_string);
- break;
- case 'g':
- tmp_mask = string_to_mode('g', access_string);
- break;
- case 'o':
- tmp_mask = string_to_mode('o', access_string);
- break;
- case 'a':
- tmp_mask = string_to_mode('a', access_string);
- break;
- case '=':
- case '+':
- case '-':
- tmp_mask = string_to_mode('a', access_string);
- break;
- }
- if (!tmp_mask.has_value()) {
- warnln("chmod: invalid mode: {}", arguments.strings[1]);
- return 1;
- }
- mask |= tmp_mask.value();
- }
- }
-
- /* set the mask for each file's permissions */
- size_t i = 2;
- while (i < arguments.strings.size()) {
+ for (size_t i = 2; i < arguments.strings.size(); ++i) {
auto current_access = TRY(Core::System::stat(arguments.strings[i]));
- /* found the minimal CNF by The Quine–McCluskey algorithm and use it */
- mode_t mode = mask.get_applying_mask()
- | (current_access.st_mode & ~mask.get_removal_mask());
- TRY(Core::System::chmod(arguments.strings[i++], mode));
+ TRY(Core::System::chmod(arguments.strings[i], mask.apply(current_access.st_mode)));
}
return 0;
}
-
-Optional<Mask> string_to_mode(char access_scope, StringView access_string)
-{
- auto get_operation = [](StringView s) {
- for (auto c : s) {
- if (c == '+' || c == '-' || c == '=')
- return c;
- }
- return ' ';
- };
-
- auto operation = get_operation(access_string);
- if (operation == ' ') {
- return {};
- }
-
- Mask mask;
- if (operation == '=') {
- switch (access_scope) {
- case 'u':
- mask.get_removal_mask() = (S_IRUSR | S_IWUSR | S_IXUSR);
- break;
- case 'g':
- mask.get_removal_mask() = (S_IRGRP | S_IWGRP | S_IXGRP);
- break;
- case 'o':
- mask.get_removal_mask() = (S_IROTH | S_IWOTH | S_IXOTH);
- break;
- case 'a':
- mask.get_removal_mask() = (S_IRUSR | S_IWUSR | S_IXUSR
- | S_IRGRP | S_IWGRP | S_IXGRP
- | S_IROTH | S_IWOTH | S_IXOTH);
- break;
- }
- operation = '+';
- }
-
- for (size_t i = 1; i < access_string.length(); i++) {
- char permission = access_string[i];
- if (permission == '+' || permission == '-' || permission == '=')
- continue;
-
- Optional<Mask> tmp_mask;
- tmp_mask = apply_permission(access_scope, permission, operation);
- if (!tmp_mask.has_value()) {
- return {};
- }
- mask |= tmp_mask.value();
- }
-
- return mask;
-}
-
-Optional<Mask> apply_permission(char access_scope, char permission, char operation)
-{
- if (permission != 'r' && permission != 'w' && permission != 'x') {
- return {};
- }
-
- Mask mask;
- mode_t tmp_mask = 0;
- switch (access_scope) {
- case 'u':
- switch (permission) {
- case 'r':
- tmp_mask = S_IRUSR;
- break;
- case 'w':
- tmp_mask = S_IWUSR;
- break;
- case 'x':
- tmp_mask = S_IXUSR;
- break;
- }
- break;
- case 'g':
- switch (permission) {
- case 'r':
- tmp_mask = S_IRGRP;
- break;
- case 'w':
- tmp_mask = S_IWGRP;
- break;
- case 'x':
- tmp_mask = S_IXGRP;
- break;
- }
- break;
- case 'o':
- switch (permission) {
- case 'r':
- tmp_mask = S_IROTH;
- break;
- case 'w':
- tmp_mask = S_IWOTH;
- break;
- case 'x':
- tmp_mask = S_IXOTH;
- break;
- }
- break;
- case 'a':
- mask |= apply_permission('u', permission, operation).value();
- mask |= apply_permission('g', permission, operation).value();
- mask |= apply_permission('o', permission, operation).value();
- break;
- }
-
- if (operation == '+') {
- mask.get_applying_mask() |= tmp_mask;
- } else {
- mask.get_removal_mask() |= tmp_mask;
- }
-
- return mask;
-}