summaryrefslogtreecommitdiff
path: root/Userland/Services/FileOperation
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@gmail.com>2021-06-17 16:17:44 +0100
committerAndreas Kling <kling@serenityos.org>2021-07-22 12:48:44 +0200
commita1b4ec15075ca49d3b6a8d1801b9c0ffe035cf24 (patch)
tree50e71f0bf17e722199655a33400a30964503ebcb /Userland/Services/FileOperation
parent516764ef17826f0b2e907851b1d0d50772106b38 (diff)
downloadserenity-a1b4ec15075ca49d3b6a8d1801b9c0ffe035cf24.zip
FileOperation: Extract execute_work_items() from perform_copy()
This is in preparation for a perform_move() function.
Diffstat (limited to 'Userland/Services/FileOperation')
-rw-r--r--Userland/Services/FileOperation/main.cpp106
1 files changed, 61 insertions, 45 deletions
diff --git a/Userland/Services/FileOperation/main.cpp b/Userland/Services/FileOperation/main.cpp
index 3c06196a72..49b22a7a81 100644
--- a/Userland/Services/FileOperation/main.cpp
+++ b/Userland/Services/FileOperation/main.cpp
@@ -13,7 +13,19 @@
#include <sched.h>
#include <sys/stat.h>
+struct WorkItem {
+ enum class Type {
+ CreateDirectory,
+ CopyFile,
+ };
+ Type type;
+ String source;
+ String destination;
+ off_t size;
+};
+
static int perform_copy(Vector<String> const& sources, String const& destination);
+static int execute_work_items(Vector<WorkItem> const& items);
static void report_error(String message);
static void report_warning(String message);
@@ -24,7 +36,7 @@ int main(int argc, char** argv)
String destination;
Core::ArgsParser args_parser;
- args_parser.add_positional_argument(operation, "Operation", "operation", Core::ArgsParser::Required::Yes);
+ args_parser.add_positional_argument(operation, "Operation: either 'Copy' or 'Move'", "operation", Core::ArgsParser::Required::Yes);
args_parser.add_positional_argument(sources, "Sources", "sources", Core::ArgsParser::Required::Yes);
args_parser.add_positional_argument(destination, "Destination", "destination", Core::ArgsParser::Required::Yes);
args_parser.parse(argc, argv);
@@ -36,17 +48,6 @@ int main(int argc, char** argv)
return 0;
}
-struct WorkItem {
- enum class Type {
- CreateDirectory,
- CopyFile,
- };
- Type type;
- String source;
- String destination;
- off_t size;
-};
-
static void report_error(String message)
{
outln("ERROR {}", message);
@@ -108,59 +109,74 @@ int perform_copy(Vector<String> const& sources, String const& destination)
return 1;
}
- off_t total_bytes_to_copy = 0;
+ return execute_work_items(items);
+}
+
+int execute_work_items(Vector<WorkItem> const& items)
+{
+ off_t total_work_bytes = 0;
for (auto& item : items)
- total_bytes_to_copy += item.size;
+ total_work_bytes += item.size;
- off_t bytes_copied_so_far = 0;
+ off_t executed_work_bytes = 0;
for (size_t i = 0; i < items.size(); ++i) {
auto& item = items[i];
off_t item_done = 0;
auto print_progress = [&] {
- outln("PROGRESS {} {} {} {} {} {} {}", i, items.size(), bytes_copied_so_far, total_bytes_to_copy, item_done, item.size, item.source);
+ outln("PROGRESS {} {} {} {} {} {} {}", i, items.size(), executed_work_bytes, total_work_bytes, item_done, item.size, item.source);
};
- if (item.type == WorkItem::Type::CreateDirectory) {
+
+ switch (item.type) {
+
+ case WorkItem::Type::CreateDirectory: {
outln("MKDIR {}", item.destination);
if (mkdir(item.destination.characters(), 0755) < 0 && errno != EEXIST) {
auto original_errno = errno;
report_error(String::formatted("mkdir: {}", strerror(original_errno)));
return 1;
}
- continue;
- }
- VERIFY(item.type == WorkItem::Type::CopyFile);
- auto source_file_or_error = Core::File::open(item.source, Core::OpenMode::ReadOnly);
- if (source_file_or_error.is_error()) {
- report_warning(String::formatted("Failed to open {} for reading: {}", item.source, source_file_or_error.error()));
- return 1;
- }
- auto destination_file_or_error = Core::File::open(item.destination, (Core::OpenMode)(Core::OpenMode::WriteOnly | Core::OpenMode::Truncate));
- if (destination_file_or_error.is_error()) {
- report_warning(String::formatted("Failed to open {} for write: {}", item.destination, destination_file_or_error.error()));
- return 1;
+ break;
}
- auto& source_file = *source_file_or_error.value();
- auto& destination_file = *destination_file_or_error.value();
- while (true) {
- print_progress();
- auto buffer = source_file.read(65536);
- if (buffer.is_empty())
- break;
- if (!destination_file.write(buffer)) {
- report_warning(String::formatted("Failed to write to destination file: {}", destination_file.error_string()));
+ case WorkItem::Type::CopyFile: {
+ auto source_file_or_error = Core::File::open(item.source, Core::OpenMode::ReadOnly);
+ if (source_file_or_error.is_error()) {
+ report_warning(String::formatted("Failed to open {} for reading: {}", item.source, source_file_or_error.error()));
return 1;
}
- item_done += buffer.size();
- bytes_copied_so_far += buffer.size();
+ auto destination_file_or_error = Core::File::open(item.destination, (Core::OpenMode)(Core::OpenMode::WriteOnly | Core::OpenMode::Truncate));
+ if (destination_file_or_error.is_error()) {
+ report_warning(String::formatted("Failed to open {} for write: {}", item.destination, destination_file_or_error.error()));
+ return 1;
+ }
+ auto& source_file = *source_file_or_error.value();
+ auto& destination_file = *destination_file_or_error.value();
+
+ while (true) {
+ print_progress();
+ auto buffer = source_file.read(65536);
+ if (buffer.is_empty())
+ break;
+ if (!destination_file.write(buffer)) {
+ report_warning(String::formatted("Failed to write to destination file: {}", destination_file.error_string()));
+ return 1;
+ }
+ item_done += buffer.size();
+ executed_work_bytes += buffer.size();
+ print_progress();
+ // FIXME: Remove this once the kernel is smart enough to schedule other threads
+ // while we're doing heavy I/O. Right now, copying a large file will totally
+ // starve the rest of the system.
+ sched_yield();
+ }
print_progress();
- // FIXME: Remove this once the kernel is smart enough to schedule other threads
- // while we're doing heavy I/O. Right now, copying a large file will totally
- // starve the rest of the system.
- sched_yield();
+ break;
+ }
+
+ default:
+ VERIFY_NOT_REACHED();
}
- print_progress();
}
outln("FINISH");