From d638cd50f41cb18ccedc07b0341e1e02cdcc8e76 Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Sun, 19 Apr 2026 13:02:03 +0100 Subject: [PATCH] Remove pv_bound_long() and the blanket 100,000 hour cutoff - instead, clamp the ETA to just under 100,000 hours (to keep it from getting too wide), clamp the FINETA to a max of 7,000 years (to keep the date the same width), and make the timer show an overflow message when 1,000,000 days is reached. --- src/include/pv-internal.h | 1 - src/pv/display.c | 10 ---------- src/pv/format/eta.c | 14 ++++++++------ src/pv/format/fineta.c | 15 ++++++++++----- src/pv/format/timer.c | 27 +++++++++++++++------------ 5 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index c7f547c..f3db38c 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -557,7 +557,6 @@ struct pvdisplay_component_s { int pv_main_loop(pvstate_t); void pv_calculate_transfer_rate(pvtransfercalc_t, readonly_pvtransferstate_t, readonly_pvcontrol_t, readonly_pvdisplay_t, bool); -long pv_bound_long(long, long, long); long pv_seconds_remaining(const off_t, const off_t, const long double); void pv_si_prefix(long double *, char *, const long double, pvtransfercount_t); void pv_describe_amount(char *, size_t, char *, long double, char *, char *, pvtransfercount_t); diff --git a/src/pv/display.c b/src/pv/display.c index c61ef31..eb32219 100644 --- a/src/pv/display.c +++ b/src/pv/display.c @@ -233,16 +233,6 @@ void pv_screensize(unsigned int *width, unsigned int *height) } -/* - * Return the original value x so that it has been clamped between - * [min..max] - */ -long pv_bound_long(long x, long min, long max) -{ - return x < min ? min : x > max ? max : x; -} - - /* * Given how many bytes have been transferred, the total byte count to * transfer, and the current average transfer rate, return the estimated diff --git a/src/pv/format/eta.c b/src/pv/format/eta.c index 5e2aadd..c31d115 100644 --- a/src/pv/format/eta.c +++ b/src/pv/format/eta.c @@ -16,7 +16,7 @@ */ pvdisplay_bytecount_t pv_formatter_eta(pvformatter_args_t args) { - char content[128]; /* flawfinder: ignore - always bounded */ + char content[128]; /* flawfinder: ignore - bounded in pv_snprintf(). */ long eta; content[0] = '\0'; @@ -34,11 +34,13 @@ pvdisplay_bytecount_t pv_formatter_eta(pvformatter_args_t args) pv_seconds_remaining((args->transfer->transferred - args->display->initial_offset), args->control->size - args->display->initial_offset, args->calc->current_avg_rate); - /* - * Bounds check, to keep within the suffix buffer. This means the - * ETA will always be less than 100,000 hours. - */ - eta = pv_bound_long(eta, 0, (long) 360000000L); + /* The ETA must always be positive. */ + if (eta < 0) + eta = 0; + + /* The ETA must be under 100,000 days so it's not too wide. */ + if ((eta / 86400L) >= 100000L) + eta = 100000L * 86400L - 1L; /* * If the ETA is more than a day, include a day count as well as diff --git a/src/pv/format/fineta.c b/src/pv/format/fineta.c index 289dca4..c587b46 100644 --- a/src/pv/format/fineta.c +++ b/src/pv/format/fineta.c @@ -20,7 +20,7 @@ */ pvdisplay_bytecount_t pv_formatter_fineta(pvformatter_args_t args) { - char content[128]; /* flawfinder: ignore - always bounded */ + char content[128]; /* flawfinder: ignore - bounded by strftime(). */ time_t now, then; struct tm *time_ptr; long eta; @@ -43,15 +43,20 @@ pvdisplay_bytecount_t pv_formatter_fineta(pvformatter_args_t args) time_format = NULL; /* - * The completion clock time may be hidden by a failed localtime - * lookup. + * Note that the completion clock time may be hidden by a failed + * localtime lookup. */ eta = pv_seconds_remaining(args->transfer->transferred - args->display->initial_offset, args->control->size - args->display->initial_offset, args->calc->current_avg_rate); - /* Bounds check - see pv_formatter_eta(). */ - eta = pv_bound_long(eta, 0, (long) 360000000L); + /* The ETA must always be positive. */ + if (eta < 0) + eta = 0; + + /* Clamp the ETA to 7,000 years max so the date isn't too wide. */ + if ((eta / 31536000L) > 7000L) + eta = 31536000L * 7000L; /* * Only include the date if the ETA is more than 6 hours diff --git a/src/pv/format/timer.c b/src/pv/format/timer.c index f429d7b..ae34c5d 100644 --- a/src/pv/format/timer.c +++ b/src/pv/format/timer.c @@ -16,7 +16,7 @@ */ pvdisplay_bytecount_t pv_formatter_timer(pvformatter_args_t args) { - char content[128]; /* flawfinder: ignore - always bounded */ + char content[128]; /* flawfinder: ignore - bounded with pv_snprintf(). */ long double elapsed_seconds; args->display->showing_timer = true; @@ -28,21 +28,24 @@ pvdisplay_bytecount_t pv_formatter_timer(pvformatter_args_t args) elapsed_seconds = args->transfer->elapsed_seconds; - /* - * Bounds check, to stay within the prefix buffer. This does mean - * that the timer will stop at a 100,000 hours, but since that's 11 - * years, it shouldn't be a problem. - */ - if (elapsed_seconds > (long double) 360000000.0L) - elapsed_seconds = (long double) 360000000.0L; - - /* Also check it's not negative. */ - if (elapsed_seconds < 0.0) - elapsed_seconds = 0.0; + /* The timer must always be positive. */ + if (elapsed_seconds < 0.0L) + elapsed_seconds = 0.0L; if (args->control->numeric) { /* Numeric mode - show the number of seconds, unformatted. */ (void) pv_snprintf(content, sizeof(content), "%.4Lf", elapsed_seconds); + } else if (elapsed_seconds > (long double) (999999.999999L * 86400.0L)) { + /* + * At a million days, the timer would be too wide, so avoid + * an overflow. + */ + (void) pv_snprintf(content, + sizeof(content), + "%s:%02ld:%02ld:%02ld", + ">=1e6", + (((long) (elapsed_seconds)) / 3600) % + 24, (((long) (elapsed_seconds)) / 60) % 60, ((long) (elapsed_seconds)) % 60); } else if (elapsed_seconds > (long double) 86400.0L) { /* * If the elapsed time is more than a day, include a day count as