diff options
author | Sam Atkins <atkinssj@gmail.com> | 2021-06-22 15:45:55 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-22 12:48:44 +0200 |
commit | 967314023c0af9e900a58dfb1ce0b1362a29c445 (patch) | |
tree | cf8919e6aedc2c6985335fc2308cb70829834e0d /Userland/Services/FileOperation/main.cpp | |
parent | e99200cc23c8ddf45ac93fd6236a5dd137921b1c (diff) | |
download | serenity-967314023c0af9e900a58dfb1ce0b1362a29c445.zip |
FileOperation: Implement 'Delete' operation
Diffstat (limited to 'Userland/Services/FileOperation/main.cpp')
-rw-r--r-- | Userland/Services/FileOperation/main.cpp | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/Userland/Services/FileOperation/main.cpp b/Userland/Services/FileOperation/main.cpp index 22b7a36b8c..829ad6803d 100644 --- a/Userland/Services/FileOperation/main.cpp +++ b/Userland/Services/FileOperation/main.cpp @@ -20,6 +20,7 @@ struct WorkItem { DeleteDirectory, CopyFile, MoveFile, + DeleteFile, }; Type type; String source; @@ -29,6 +30,7 @@ struct WorkItem { static int perform_copy(Vector<String> const& sources, String const& destination); static int perform_move(Vector<String> const& sources, String const& destination); +static int perform_delete(Vector<String> const& sources); static int execute_work_items(Vector<WorkItem> const& items); static void report_error(String message); static void report_warning(String message); @@ -39,10 +41,13 @@ int main(int argc, char** argv) Vector<String> paths; Core::ArgsParser args_parser; - args_parser.add_positional_argument(operation, "Operation: either 'Copy' or 'Move'", "operation", Core::ArgsParser::Required::Yes); + args_parser.add_positional_argument(operation, "Operation: either 'Copy', 'Move' or 'Delete'", "operation", Core::ArgsParser::Required::Yes); args_parser.add_positional_argument(paths, "Source paths, followed by a destination if applicable", "paths", Core::ArgsParser::Required::Yes); args_parser.parse(argc, argv); + if (operation == "Delete") + return perform_delete(paths); + String destination = paths.take_last(); if (paths.is_empty()) { report_warning("At least one source and destination are required"); @@ -183,6 +188,56 @@ int perform_move(Vector<String> const& sources, String const& destination) return execute_work_items(items); } +static bool collect_delete_work_items(String const& source, Vector<WorkItem>& items) +{ + struct stat st = {}; + if (stat(source.characters(), &st) < 0) { + auto original_errno = errno; + report_error(String::formatted("stat: {}", strerror(original_errno))); + return false; + } + + if (!S_ISDIR(st.st_mode)) { + // It's a file. + items.append(WorkItem { + .type = WorkItem::Type::DeleteFile, + .source = source, + .destination = {}, + .size = st.st_size, + }); + return true; + } + + // It's a directory. + Core::DirIterator dt(source, Core::DirIterator::SkipParentAndBaseDir); + while (dt.has_next()) { + auto name = dt.next_path(); + if (!collect_delete_work_items(String::formatted("{}/{}", source, name), items)) + return false; + } + + items.append(WorkItem { + .type = WorkItem::Type::DeleteDirectory, + .source = source, + .destination = {}, + .size = 0, + }); + + return true; +} + +int perform_delete(Vector<String> const& sources) +{ + Vector<WorkItem> items; + + for (auto& source : sources) { + if (!collect_delete_work_items(source, items)) + return 1; + } + + return execute_work_items(items); +} + int execute_work_items(Vector<WorkItem> const& items) { off_t total_work_bytes = 0; @@ -288,6 +343,20 @@ int execute_work_items(Vector<WorkItem> const& items) break; } + case WorkItem::Type::DeleteFile: { + if (unlink(item.source.characters()) < 0) { + auto original_errno = errno; + report_error(String::formatted("unlink: {}", strerror(original_errno))); + return 1; + } + + item_done += item.size; + executed_work_bytes += item.size; + print_progress(); + + break; + } + default: VERIFY_NOT_REACHED(); } |