mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:07:34 +00:00
cp: Implement the granular --preserve
flag
This commit is contained in:
parent
69e0b8dbb7
commit
bb0feebddc
1 changed files with 34 additions and 9 deletions
|
@ -17,7 +17,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
TRY(Core::System::pledge("stdio rpath wpath cpath fattr chown"));
|
TRY(Core::System::pledge("stdio rpath wpath cpath fattr chown"));
|
||||||
|
|
||||||
bool link = false;
|
bool link = false;
|
||||||
bool preserve = false;
|
auto preserve = Core::File::PreserveMode::Nothing;
|
||||||
bool recursion_allowed = false;
|
bool recursion_allowed = false;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
Vector<StringView> sources;
|
Vector<StringView> sources;
|
||||||
|
@ -25,7 +25,37 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.add_option(link, "Link files instead of copying", "link", 'l');
|
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, "Copy directories recursively", "recursive", 'R');
|
||||||
args_parser.add_option(recursion_allowed, "Same as -R", nullptr, 'r');
|
args_parser.add_option(recursion_allowed, "Same as -R", nullptr, 'r');
|
||||||
args_parser.add_option(verbose, "Verbose", "verbose", 'v');
|
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.add_positional_argument(destination, "Destination file path", "destination");
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
if (preserve) {
|
if (has_flag(preserve, Core::File::PreserveMode::Permissions)) {
|
||||||
umask(0);
|
umask(0);
|
||||||
} else {
|
} else {
|
||||||
TRY(Core::System::pledge("stdio rpath wpath cpath fattr"));
|
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);
|
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) {
|
for (auto& source : sources) {
|
||||||
auto destination_path = destination_is_existing_dir
|
auto destination_path = destination_is_existing_dir
|
||||||
? String::formatted("{}/{}", destination, LexicalPath::basename(source))
|
? 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,
|
recursion_allowed ? Core::File::RecursionMode::Allowed : Core::File::RecursionMode::Disallowed,
|
||||||
link ? Core::File::LinkMode::Allowed : Core::File::LinkMode::Disallowed,
|
link ? Core::File::LinkMode::Allowed : Core::File::LinkMode::Disallowed,
|
||||||
Core::File::AddDuplicateFileMarker::No,
|
Core::File::AddDuplicateFileMarker::No,
|
||||||
preserve_mode);
|
preserve);
|
||||||
|
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
if (result.error().tried_recursing)
|
if (result.error().tried_recursing)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue