Sfoglia il codice sorgente

chmod: Use FilePermissionsMask to handle mode argument

Xavier Defrang 3 anni fa
parent
commit
005b0f7384
1 ha cambiato i file con 6 aggiunte e 212 eliminazioni
  1. 6 212
      Userland/Utilities/chmod.cpp

+ 6 - 212
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;
-}