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

chmod: Port to LibMain :^)

This ports chmod to LibMain + changes input parameters on several
functions from raw C strings to StringView.
This commit is contained in:
Kenneth Myhra 2021-11-27 15:55:40 +01:00 committed by Brian Gianforcaro
parent 0d76d15f9d
commit d465d3a457
2 changed files with 41 additions and 39 deletions

View file

@ -62,6 +62,7 @@ target_link_libraries(bt LibSymbolication LibMain)
target_link_libraries(blockdev LibMain) target_link_libraries(blockdev LibMain)
target_link_libraries(cat LibMain) target_link_libraries(cat LibMain)
target_link_libraries(checksum LibCrypto) target_link_libraries(checksum LibCrypto)
target_link_libraries(chmod LibMain)
target_link_libraries(chres LibGUI) target_link_libraries(chres LibGUI)
target_link_libraries(cksum LibCrypto) target_link_libraries(cksum LibCrypto)
target_link_libraries(config LibConfig) target_link_libraries(config LibConfig)

View file

@ -1,15 +1,19 @@
/* /*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Kenneth Myhra <kennethmyhra@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <AK/Format.h> #include <AK/Format.h>
#include <AK/Optional.h> #include <AK/Optional.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <LibCore/System.h>
#include <LibMain/Main.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h>
/* the new mode will be computed using the boolean function(for each bit): /* the new mode will be computed using the boolean function(for each bit):
@ -48,17 +52,14 @@ public:
mode_t& get_applying_mask() { return applying_mask; } mode_t& get_applying_mask() { return applying_mask; }
}; };
Optional<Mask> string_to_mode(char access_scope, const char*& access_string); Optional<Mask> string_to_mode(char access_scope, StringView access_string);
Optional<Mask> apply_permission(char access_scope, char permission, char operation); Optional<Mask> apply_permission(char access_scope, char permission, char operation);
int main(int argc, char** argv) ErrorOr<int> serenity_main(Main::Arguments arguments)
{ {
if (pledge("stdio rpath fattr", nullptr) < 0) { TRY(Core::System::pledge("stdio rpath fattr", nullptr));
perror("pledge");
return 1;
}
if (argc < 3) { if (arguments.strings.size() < 3) {
warnln("usage: chmod <octal-mode> <path...>"); warnln("usage: chmod <octal-mode> <path...>");
warnln(" chmod [[ugoa][+-=][rwx...],...] <path...>"); warnln(" chmod [[ugoa][+-=][rwx...],...] <path...>");
return 1; return 1;
@ -67,41 +68,38 @@ int main(int argc, char** argv)
Mask mask; Mask mask;
/* compute a mask */ /* compute a mask */
if (argv[1][0] >= '0' && argv[1][0] <= '7') {
if (sscanf(argv[1], "%ho", &mask.get_applying_mask()) != 1) { if (arguments.strings[1][0] >= '0' && arguments.strings[1][0] <= '7') {
if (sscanf(arguments.strings[1].to_string().characters(), "%ho", &mask.get_applying_mask()) != 1) {
perror("sscanf"); perror("sscanf");
return 1; return 1;
} }
mask.get_removal_mask() = ~mask.get_applying_mask(); mask.get_removal_mask() = ~mask.get_applying_mask();
} else { } else {
const char* access_string = argv[1]; auto access_strings = arguments.strings[1].split_view(',');
for (auto access_string : access_strings) {
while (*access_string != '\0') {
Optional<Mask> tmp_mask; Optional<Mask> tmp_mask;
switch (*access_string) { switch (access_string[0]) {
case 'u': case 'u':
tmp_mask = string_to_mode('u', ++access_string); tmp_mask = string_to_mode('u', access_string);
break; break;
case 'g': case 'g':
tmp_mask = string_to_mode('g', ++access_string); tmp_mask = string_to_mode('g', access_string);
break; break;
case 'o': case 'o':
tmp_mask = string_to_mode('o', ++access_string); tmp_mask = string_to_mode('o', access_string);
break; break;
case 'a': case 'a':
tmp_mask = string_to_mode('a', ++access_string); tmp_mask = string_to_mode('a', access_string);
break; break;
case '=': case '=':
case '+': case '+':
case '-': case '-':
tmp_mask = string_to_mode('a', access_string); tmp_mask = string_to_mode('a', access_string);
break; break;
case ',':
++access_string;
continue;
} }
if (!tmp_mask.has_value()) { if (!tmp_mask.has_value()) {
warnln("chmod: invalid mode: {}", argv[1]); warnln("chmod: invalid mode: {}", arguments.strings[1]);
return 1; return 1;
} }
mask |= tmp_mask.value(); mask |= tmp_mask.value();
@ -109,29 +107,30 @@ int main(int argc, char** argv)
} }
/* set the mask for each file's permissions */ /* set the mask for each file's permissions */
struct stat current_access; size_t i = 2;
int i = 2; while (i < arguments.strings.size()) {
while (i < argc) { auto current_access = TRY(Core::System::stat(arguments.strings[i]));
if (stat(argv[i], &current_access) != 0) {
perror("stat");
return 1;
}
/* found the minimal CNF by The QuineMcCluskey algorithm and use it */ /* found the minimal CNF by The QuineMcCluskey algorithm and use it */
mode_t mode = mask.get_applying_mask() mode_t mode = mask.get_applying_mask()
| (current_access.st_mode & ~mask.get_removal_mask()); | (current_access.st_mode & ~mask.get_removal_mask());
if (chmod(argv[i++], mode) != 0) { TRY(Core::System::chmod(arguments.strings[i++], mode));
perror("chmod");
}
} }
return 0; return 0;
} }
Optional<Mask> string_to_mode(char access_scope, const char*& access_string) Optional<Mask> string_to_mode(char access_scope, StringView access_string)
{ {
char operation = *access_string; auto get_operation = [](StringView s) {
for (auto c : s) {
if (c == '+' || c == '-' || c == '=')
return c;
}
return ' ';
};
if (operation != '+' && operation != '-' && operation != '=') { auto operation = get_operation(access_string);
if (operation == ' ') {
return {}; return {};
} }
@ -156,15 +155,17 @@ Optional<Mask> string_to_mode(char access_scope, const char*& access_string)
operation = '+'; operation = '+';
} }
access_string++; for (size_t i = 1; i < access_string.length(); i++) {
while (*access_string != '\0' && *access_string != ',') { char permission = access_string[i];
if (permission == '+' || permission == '-' || permission == '=')
continue;
Optional<Mask> tmp_mask; Optional<Mask> tmp_mask;
tmp_mask = apply_permission(access_scope, *access_string, operation); tmp_mask = apply_permission(access_scope, permission, operation);
if (!tmp_mask.has_value()) { if (!tmp_mask.has_value()) {
return {}; return {};
} }
mask |= tmp_mask.value(); mask |= tmp_mask.value();
access_string++;
} }
return mask; return mask;