diff --git a/Userland/Utilities/mknod.cpp b/Userland/Utilities/mknod.cpp index 1cc714c976..719c0ad848 100644 --- a/Userland/Utilities/mknod.cpp +++ b/Userland/Utilities/mknod.cpp @@ -1,11 +1,13 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2023, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include +#include #include #include #include @@ -16,6 +18,7 @@ ErrorOr serenity_main(Main::Arguments arguments) { TRY(Core::System::pledge("stdio dpath")); + StringView mode_string { "0666"sv }; StringView name; StringView type_string; StringView major_string; @@ -23,53 +26,58 @@ ErrorOr serenity_main(Main::Arguments arguments) Core::ArgsParser args_parser; args_parser.set_general_help("Creates a file system node."); + args_parser.add_option(mode_string, "File mode in octal or symbolic notation", "mode", 'm', "mode"); args_parser.add_positional_argument(name, "Pathname to create", "name", Core::ArgsParser::Required::Yes); - args_parser.add_positional_argument(type_string, "Type of file to create", "type", Core::ArgsParser::Required::Yes); + args_parser.add_positional_argument( + type_string, + "Type of file to create " + "\n\t\tb\tcreate a block special file" + "\n\t\tc, u\tcreate a character special file" + "\n\t\tp\tcreate a FIFO", + "type", + Core::ArgsParser::Required::Yes); args_parser.add_positional_argument(major_string, "Major device number", "major", Core::ArgsParser::Required::No); args_parser.add_positional_argument(minor_string, "Minor device number", "minor", Core::ArgsParser::Required::No); args_parser.parse(arguments); - // FIXME: Add some kind of option for specifying the file permissions. - - mode_t mode = 0666; + auto mask = TRY(Core::FilePermissionsMask::parse(mode_string)); char type = type_string[0]; + mode_t mode; switch (type) { case 'c': case 'u': - mode |= S_IFCHR; + mode = mask.apply(S_IFCHR); break; case 'b': - mode |= S_IFBLK; + mode = mask.apply(S_IFBLK); break; case 'p': - mode |= S_IFIFO; + mode = mask.apply(S_IFIFO); break; default: warnln("Invalid device type {}", type); return 1; } + auto maybe_major = major_string.to_int(); + auto maybe_minor = minor_string.to_int(); + dev_t device; if (type == 'p') { - if (!major_string.is_empty() || !minor_string.is_empty()) { + if (maybe_major.has_value() || maybe_minor.has_value()) { warnln("Do not set device numbers when creating FIFO"); return 1; } + device = makedev(0, 0); } else { - if (major_string.is_empty() || minor_string.is_empty()) { + if (!(maybe_major.has_value() && maybe_minor.has_value())) { warnln("Major and minor device numbers are required"); return 1; } + device = makedev(maybe_major.value(), maybe_minor.value()); } - int major = 0; - int minor = 0; - if (type != 'p') { - major = atoi(major_string.characters_without_null_termination()); - minor = atoi(minor_string.characters_without_null_termination()); - } - - TRY(Core::System::mknod(name, mode, makedev(major, minor))); + TRY(Core::System::mknod(name, mode, device)); return 0; }