dd: Show statistics also after receiving an interrupt signal

This commit is contained in:
Karol Kosek 2023-05-31 18:54:38 +02:00 committed by Jelle Raaijmakers
parent f12dc8b7f5
commit 2f6c99dce5
Notes: sideshowbarker 2024-07-17 22:41:14 +09:00

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, János Tóth <toth-janos@outlook.com>
* Copyright (c) 2023, Karol Kosek <krkk@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -8,6 +9,7 @@
#include <AK/DeprecatedString.h>
#include <AK/Optional.h>
#include <AK/Vector.h>
#include <LibCore/System.h>
#include <LibMain/Main.h>
#include <fcntl.h>
#include <stdint.h>
@ -36,6 +38,22 @@ enum Status {
Noxfer
};
struct {
Status status = Default;
size_t total_bytes_copied = 0;
size_t total_blocks_in = 0, partial_blocks_in = 0;
size_t total_blocks_out = 0, partial_blocks_out = 0;
} statistics;
static void closing_statistics()
{
if (statistics.status != Default)
return;
warnln("{}+{} blocks in", statistics.total_blocks_in, statistics.partial_blocks_in);
warnln("{}+{} blocks out", statistics.total_blocks_out, statistics.partial_blocks_out);
warnln("{} bytes copied.", statistics.total_bytes_copied);
}
static StringView split_at_equals(StringView argument)
{
auto values = argument.split_view('=', SplitBehavior::KeepEmpty);
@ -134,11 +152,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
size_t count = 0;
size_t skip = 0;
size_t seek = 0;
Status status = Default;
size_t total_bytes_copied = 0;
size_t total_blocks_in = 0, partial_blocks_in = 0;
size_t total_blocks_out = 0, partial_blocks_out = 0;
uint8_t* buffer = nullptr;
ssize_t nread = 0, nwritten = 0;
@ -173,7 +187,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
return 1;
}
} else if (argument.starts_with("status="sv)) {
if (handle_status_arguments(status, argument) < 0) {
if (handle_status_arguments(statistics.status, argument) < 0) {
return 1;
}
} else {
@ -194,6 +208,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
}
}
TRY(Core::System::signal(SIGINT, [](int status) {
closing_statistics();
exit(status);
}));
while (1) {
nread = read(input_fd, buffer, block_size);
if (nread < 0) {
@ -203,12 +222,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
break;
} else {
if ((size_t)nread != block_size) {
partial_blocks_in++;
statistics.partial_blocks_in++;
} else {
total_blocks_in++;
statistics.total_blocks_in++;
}
if (partial_blocks_in + total_blocks_in <= skip) {
if (statistics.partial_blocks_in + statistics.total_blocks_in <= skip) {
continue;
}
@ -220,25 +239,21 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
break;
} else {
if ((size_t)nwritten < block_size) {
partial_blocks_out++;
statistics.partial_blocks_out++;
} else {
total_blocks_out++;
statistics.total_blocks_out++;
}
total_bytes_copied += nwritten;
statistics.total_bytes_copied += nwritten;
if (count > 0 && (partial_blocks_out + total_blocks_out) >= count) {
if (count > 0 && (statistics.partial_blocks_out + statistics.total_blocks_out) >= count) {
break;
}
}
}
}
if (status == Default) {
warnln("{}+{} blocks in", total_blocks_in, partial_blocks_in);
warnln("{}+{} blocks out", total_blocks_out, partial_blocks_out);
warnln("{} bytes copied.", total_bytes_copied);
}
closing_statistics();
free(buffer);