|
|
26a7a5 |
From c6b79cbc990b3b4933730205f58812fb44b6fcd5 Mon Sep 17 00:00:00 2001
|
|
|
26a7a5 |
From: Petr Tesarik <ptesarik@suse.cz>
|
|
|
26a7a5 |
Date: Tue, 10 Apr 2018 20:39:00 +0900
|
|
|
26a7a5 |
Subject: [PATCH] [PATCH v2] makedumpfile: Use integer arithmetics for the
|
|
|
26a7a5 |
progress bar
|
|
|
26a7a5 |
|
|
|
26a7a5 |
Essentially, the estimated remaining time is calculated as:
|
|
|
26a7a5 |
|
|
|
26a7a5 |
elapsed * (100 - progress) / progress
|
|
|
26a7a5 |
|
|
|
26a7a5 |
Since the calculation is done with floating point numbers, it had
|
|
|
26a7a5 |
masked a division by zero (if progress is 0), producing a NaN or
|
|
|
26a7a5 |
infinity. The following conversion to int produces INT_MIN with GCC
|
|
|
26a7a5 |
on major platforms, which originally overflowed the eta buffer. This
|
|
|
26a7a5 |
bug was fixed by commit e5f96e79d69a1d295f19130da00ec6514d28a8ae,
|
|
|
26a7a5 |
but conversion of NaN and infinity is undefined behaviour in ISO C,
|
|
|
26a7a5 |
plus the corresponding output is still wrong, e.g.:
|
|
|
26a7a5 |
|
|
|
26a7a5 |
Copying data : [ 0.0 %] / eta:
|
|
|
26a7a5 |
-9223372036854775808s
|
|
|
26a7a5 |
|
|
|
26a7a5 |
Most importantly, using the FPU for a progress bar is overkill.
|
|
|
26a7a5 |
Since the progress percentage is reported with one decimal digit
|
|
|
26a7a5 |
following the decimal point, it can be stored as an integer tenths
|
|
|
26a7a5 |
of a percent.
|
|
|
26a7a5 |
|
|
|
26a7a5 |
Second, the estimated time can be calculated in milliseconds. Up to
|
|
|
26a7a5 |
49 days can be represented this way even on 32-bit platforms. Note
|
|
|
26a7a5 |
that delta.tv_usec can be ignored in the subtraction, because the
|
|
|
26a7a5 |
resulting eta is printed as seconds, so elapsed microseconds are
|
|
|
26a7a5 |
irrelevant.
|
|
|
26a7a5 |
|
|
|
26a7a5 |
Last but not least, the original buffer overflow was probably caused
|
|
|
26a7a5 |
by the wrong assumption that integers < 100 can be interpreted with
|
|
|
26a7a5 |
less than 3 ASCII characters, but that's not true for signed
|
|
|
26a7a5 |
integers. To make eta_to_human_short() a bit safer, use an unsigned
|
|
|
26a7a5 |
integer type.
|
|
|
26a7a5 |
|
|
|
26a7a5 |
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
|
|
|
26a7a5 |
---
|
|
|
26a7a5 |
print_info.c | 43 ++++++++++++++++++++-----------------------
|
|
|
26a7a5 |
1 file changed, 20 insertions(+), 23 deletions(-)
|
|
|
26a7a5 |
|
|
|
26a7a5 |
diff --git a/makedumpfile-1.6.2/print_info.c b/makedumpfile-1.6.2/print_info.c
|
|
|
26a7a5 |
index 09e215a..6bfcd11 100644
|
|
|
26a7a5 |
--- a/makedumpfile-1.6.2/print_info.c
|
|
|
26a7a5 |
+++ b/makedumpfile-1.6.2/print_info.c
|
|
|
26a7a5 |
@@ -16,8 +16,6 @@
|
|
|
26a7a5 |
#include "print_info.h"
|
|
|
26a7a5 |
#include <time.h>
|
|
|
26a7a5 |
#include <string.h>
|
|
|
26a7a5 |
-#include <stdint.h>
|
|
|
26a7a5 |
-#include <inttypes.h>
|
|
|
26a7a5 |
|
|
|
26a7a5 |
#define PROGRESS_MAXLEN "50"
|
|
|
26a7a5 |
|
|
|
26a7a5 |
@@ -354,21 +352,18 @@ static void calc_delta(struct timeval *tv_start, struct timeval *delta)
|
|
|
26a7a5 |
}
|
|
|
26a7a5 |
|
|
|
26a7a5 |
/* produce less than 12 bytes on msg */
|
|
|
26a7a5 |
-static int eta_to_human_short (int64_t secs, char* msg, int maxsize)
|
|
|
26a7a5 |
+static int eta_to_human_short (unsigned long secs, char* msg)
|
|
|
26a7a5 |
{
|
|
|
26a7a5 |
strcpy(msg, "eta: ");
|
|
|
26a7a5 |
msg += strlen("eta: ");
|
|
|
26a7a5 |
if (secs < 100)
|
|
|
26a7a5 |
- snprintf(msg, maxsize, "%"PRId64"s", secs);
|
|
|
26a7a5 |
+ sprintf(msg, "%lus", secs);
|
|
|
26a7a5 |
else if (secs < 100 * 60)
|
|
|
26a7a5 |
- snprintf(msg, maxsize, "%"PRId64"m""%"PRId64"s",
|
|
|
26a7a5 |
- secs / 60, secs % 60);
|
|
|
26a7a5 |
+ sprintf(msg, "%lum%lus", secs / 60, secs % 60);
|
|
|
26a7a5 |
else if (secs < 48 * 3600)
|
|
|
26a7a5 |
- snprintf(msg, maxsize, "%"PRId64"h""%"PRId64"m",
|
|
|
26a7a5 |
- secs / 3600, (secs / 60) % 60);
|
|
|
26a7a5 |
+ sprintf(msg, "%luh%lum", secs / 3600, (secs / 60) % 60);
|
|
|
26a7a5 |
else if (secs < 100 * 86400)
|
|
|
26a7a5 |
- snprintf(msg, maxsize, "%"PRId64"d""%"PRId64"h",
|
|
|
26a7a5 |
- secs / 86400, (secs / 3600) % 24);
|
|
|
26a7a5 |
+ sprintf(msg, "%lud%luh", secs / 86400, (secs / 3600) % 24);
|
|
|
26a7a5 |
else
|
|
|
26a7a5 |
sprintf(msg, ">2day");
|
|
|
26a7a5 |
return 0;
|
|
|
26a7a5 |
@@ -378,37 +373,39 @@ static int eta_to_human_short (int64_t secs, char* msg, int maxsize)
|
|
|
26a7a5 |
void
|
|
|
26a7a5 |
print_progress(const char *msg, unsigned long current, unsigned long end, struct timeval *start)
|
|
|
26a7a5 |
{
|
|
|
26a7a5 |
- float progress;
|
|
|
26a7a5 |
+ unsigned progress; /* in promilles (tenths of a percent) */
|
|
|
26a7a5 |
time_t tm;
|
|
|
26a7a5 |
static time_t last_time = 0;
|
|
|
26a7a5 |
static unsigned int lapse = 0;
|
|
|
26a7a5 |
static const char *spinner = "/|\\-";
|
|
|
26a7a5 |
struct timeval delta;
|
|
|
26a7a5 |
- int64_t eta;
|
|
|
26a7a5 |
- char eta_msg[32] = " ";
|
|
|
26a7a5 |
+ unsigned long eta;
|
|
|
26a7a5 |
+ char eta_msg[16] = " ";
|
|
|
26a7a5 |
|
|
|
26a7a5 |
if (current < end) {
|
|
|
26a7a5 |
tm = time(NULL);
|
|
|
26a7a5 |
if (tm - last_time < 1)
|
|
|
26a7a5 |
return;
|
|
|
26a7a5 |
last_time = tm;
|
|
|
26a7a5 |
- progress = (float)current * 100 / end;
|
|
|
26a7a5 |
+ progress = current * 1000 / end;
|
|
|
26a7a5 |
} else
|
|
|
26a7a5 |
- progress = 100;
|
|
|
26a7a5 |
+ progress = 1000;
|
|
|
26a7a5 |
|
|
|
26a7a5 |
- if (start != NULL) {
|
|
|
26a7a5 |
+ if (start != NULL && progress != 0) {
|
|
|
26a7a5 |
calc_delta(start, &delta);
|
|
|
26a7a5 |
- eta = delta.tv_sec + delta.tv_usec / 1e6;
|
|
|
26a7a5 |
- eta = (100 - progress) * eta / progress;
|
|
|
26a7a5 |
- eta_to_human_short(eta, eta_msg, sizeof(eta_msg));
|
|
|
26a7a5 |
+ eta = 1000 * delta.tv_sec + delta.tv_usec / 1000;
|
|
|
26a7a5 |
+ eta = eta / progress - delta.tv_sec;
|
|
|
26a7a5 |
+ eta_to_human_short(eta, eta_msg);
|
|
|
26a7a5 |
}
|
|
|
26a7a5 |
if (flag_ignore_r_char) {
|
|
|
26a7a5 |
- PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%5.1f %%] %c %16s\n",
|
|
|
26a7a5 |
- msg, progress, spinner[lapse % 4], eta_msg);
|
|
|
26a7a5 |
+ PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3u.%u %%] %c %16s\n",
|
|
|
26a7a5 |
+ msg, progress / 10, progress % 10,
|
|
|
26a7a5 |
+ spinner[lapse % 4], eta_msg);
|
|
|
26a7a5 |
} else {
|
|
|
26a7a5 |
PROGRESS_MSG("\r");
|
|
|
26a7a5 |
- PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%5.1f %%] %c %16s",
|
|
|
26a7a5 |
- msg, progress, spinner[lapse % 4], eta_msg);
|
|
|
26a7a5 |
+ PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3u.%u %%] %c %16s",
|
|
|
26a7a5 |
+ msg, progress / 10, progress % 10,
|
|
|
26a7a5 |
+ spinner[lapse % 4], eta_msg);
|
|
|
26a7a5 |
}
|
|
|
26a7a5 |
lapse++;
|
|
|
26a7a5 |
}
|
|
|
26a7a5 |
--
|
|
|
26a7a5 |
2.9.5
|
|
|
26a7a5 |
|