cp: Implement the granular --preserve flag

This commit is contained in:
Tim Schumacher 2022-07-12 23:57:14 +02:00 committed by Linus Groh
parent 69e0b8dbb7
commit bb0feebddc

View file

@ -17,7 +17,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
TRY(Core::System::pledge("stdio rpath wpath cpath fattr chown"));
bool link = false;
bool preserve = false;
auto preserve = Core::File::PreserveMode::Nothing;
bool recursion_allowed = false;
bool verbose = false;
Vector<StringView> sources;
@ -25,7 +25,37 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
Core::ArgsParser args_parser;
args_parser.add_option(link, "Link files instead of copying", "link", 'l');
args_parser.add_option(preserve, "Preserve time, UID/GID and file permissions", nullptr, 'p');
args_parser.add_option({
Core::ArgsParser::OptionArgumentMode::Optional,
"Preserve a selection of mode, ownership and timestamps. Defaults to all three if the option is present but no list is given.",
"preserve",
'p',
"attributes",
[&preserve](char const* s) {
if (!s) {
preserve = Core::File::PreserveMode::Permissions | Core::File::PreserveMode::Ownership | Core::File::PreserveMode::Timestamps;
return true;
}
bool values_ok = true;
StringView { s, strlen(s) }.for_each_split_view(',', false, [&](StringView value) {
if (value == "mode"sv) {
preserve |= Core::File::PreserveMode::Permissions;
} else if (value == "ownership"sv) {
preserve |= Core::File::PreserveMode::Ownership;
} else if (value == "timestamps"sv) {
preserve |= Core::File::PreserveMode::Timestamps;
} else {
warnln("cp: Unknown or unimplemented --preserve attribute: '{}'", value);
values_ok = false;
}
});
return values_ok;
},
Core::ArgsParser::OptionHideMode::None,
});
args_parser.add_option(recursion_allowed, "Copy directories recursively", "recursive", 'R');
args_parser.add_option(recursion_allowed, "Same as -R", nullptr, 'r');
args_parser.add_option(verbose, "Verbose", "verbose", 'v');
@ -33,7 +63,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.add_positional_argument(destination, "Destination file path", "destination");
args_parser.parse(arguments);
if (preserve) {
if (has_flag(preserve, Core::File::PreserveMode::Permissions)) {
umask(0);
} else {
TRY(Core::System::pledge("stdio rpath wpath cpath fattr"));
@ -41,11 +71,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
bool destination_is_existing_dir = Core::File::is_directory(destination);
auto preserve_mode = Core::File::PreserveMode::Nothing;
if (preserve)
preserve_mode = Core::File::PreserveMode::Permissions | Core::File::PreserveMode::Ownership | Core::File::PreserveMode::Timestamps;
for (auto& source : sources) {
auto destination_path = destination_is_existing_dir
? String::formatted("{}/{}", destination, LexicalPath::basename(source))
@ -56,7 +81,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
recursion_allowed ? Core::File::RecursionMode::Allowed : Core::File::RecursionMode::Disallowed,
link ? Core::File::LinkMode::Allowed : Core::File::LinkMode::Disallowed,
Core::File::AddDuplicateFileMarker::No,
preserve_mode);
preserve);
if (result.is_error()) {
if (result.error().tried_recursing)