summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2024-07-12 19:11:26 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2024-07-12 19:11:26 +0000
commit28d93e83f3cdda369bf69a27386e0adc54ee1267 (patch)
treed977de2f4de7d96272f702559bc6a20c54fd1027
parentac6464ae21e5b914f81dba6c133eb7bb39e03228 (diff)
Rewrite bytes/sec calculation using fixed point math.
This makes signal handler safe on OpenBSD. To avoid overflows the accuracy is scaled. Above 10 minutes run time we only care about second accuracy. Between 1 seconds and 10 minutes we use millisecond accuracy. Below one second we use nanoseconds, but those numbers are probably meaningless. Signal handler problem pointed out by deraadt OK deraadt, millert, tb
-rw-r--r--bin/dd/misc.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/bin/dd/misc.c b/bin/dd/misc.c
index 68afbeb9333..cd0ba9fa41d 100644
--- a/bin/dd/misc.c
+++ b/bin/dd/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.25 2024/07/12 14:30:27 deraadt Exp $ */
+/* $OpenBSD: misc.c,v 1.26 2024/07/12 19:11:25 florian Exp $ */
/* $NetBSD: misc.c,v 1.4 1995/03/21 09:04:10 cgd Exp $ */
/*-
@@ -51,16 +51,26 @@ sig_summary(int notused)
{
int save_errno = errno;
struct timespec elapsed, now;
- double nanosecs;
+ unsigned long long bps, msec;
if (ddflags & C_NOINFO)
return;
clock_gettime(CLOCK_MONOTONIC, &now);
timespecsub(&now, &st.start, &elapsed);
- nanosecs = ((double)elapsed.tv_sec * 1000000000) + elapsed.tv_nsec;
- if (nanosecs == 0)
- nanosecs = 1;
+
+ if (elapsed.tv_sec > 600)
+ bps = st.bytes / elapsed.tv_sec;
+ else if (elapsed.tv_sec > 0) {
+ /* will overflow at ~ 30 exabytes / second */
+ msec = elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
+ if (msec == 0)
+ msec = 1;
+ bps = st.bytes * 1000 / msec;
+ } else if (elapsed.tv_nsec > 0)
+ bps = st.bytes * 1000000000 / elapsed.tv_nsec;
+ else
+ bps = st.bytes;
/* Be async safe: use dprintf(3). */
dprintf(STDERR_FILENO, "%zu+%zu records in\n%zu+%zu records out\n",
@@ -77,9 +87,8 @@ sig_summary(int notused)
if (!(ddflags & C_NOXFER)) {
dprintf(STDERR_FILENO,
"%lld bytes transferred in %lld.%03ld secs "
- "(%0.0f bytes/sec)\n", (long long)st.bytes,
- (long long)elapsed.tv_sec, elapsed.tv_nsec / 1000000,
- ((double)st.bytes * 1000000000) / nanosecs);
+ "(%llu bytes/sec)\n", (long long)st.bytes,
+ (long long)elapsed.tv_sec, elapsed.tv_nsec / 1000000, bps);
}
errno = save_errno;
}