progress bar: better overflow protection; more precise bar
function old new delta bb_progress_update 639 749 +110 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
9213a55bf0
commit
805aa9fec9
@ -1592,8 +1592,9 @@ typedef struct bb_progress_t {
|
|||||||
|
|
||||||
void bb_progress_init(bb_progress_t *p) FAST_FUNC;
|
void bb_progress_init(bb_progress_t *p) FAST_FUNC;
|
||||||
void bb_progress_update(bb_progress_t *p, const char *curfile,
|
void bb_progress_update(bb_progress_t *p, const char *curfile,
|
||||||
off_t beg_range, off_t transferred,
|
uoff_t beg_range,
|
||||||
off_t totalsize) FAST_FUNC;
|
uoff_t transferred,
|
||||||
|
uoff_t totalsize) FAST_FUNC;
|
||||||
|
|
||||||
extern const char *applet_name;
|
extern const char *applet_name;
|
||||||
|
|
||||||
|
@ -62,35 +62,45 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p)
|
|||||||
|
|
||||||
void FAST_FUNC bb_progress_update(bb_progress_t *p,
|
void FAST_FUNC bb_progress_update(bb_progress_t *p,
|
||||||
const char *curfile,
|
const char *curfile,
|
||||||
off_t beg_range,
|
uoff_t beg_range,
|
||||||
off_t transferred,
|
uoff_t transferred,
|
||||||
off_t totalsize)
|
uoff_t totalsize)
|
||||||
{
|
{
|
||||||
uoff_t beg_and_transferred;
|
uoff_t beg_and_transferred;
|
||||||
unsigned since_last_update, elapsed;
|
unsigned since_last_update, elapsed;
|
||||||
unsigned ratio;
|
unsigned ratio;
|
||||||
int barlength, i;
|
int barlength;
|
||||||
|
int kiloscale;
|
||||||
|
|
||||||
/* totalsize == 0 if it is unknown */
|
/* totalsize == 0 if it is unknown */
|
||||||
|
|
||||||
|
beg_and_transferred = beg_range + transferred;
|
||||||
|
|
||||||
elapsed = monotonic_sec();
|
elapsed = monotonic_sec();
|
||||||
since_last_update = elapsed - p->lastupdate_sec;
|
since_last_update = elapsed - p->lastupdate_sec;
|
||||||
/* Do not update on every call
|
/* Do not update on every call
|
||||||
* (we can be called on every network read!) */
|
* (we can be called on every network read!) */
|
||||||
if (since_last_update == 0 && !totalsize)
|
if (since_last_update == 0 && beg_and_transferred < totalsize)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
beg_and_transferred = beg_range + transferred;
|
/* Scale sizes down if they are close to overflowing.
|
||||||
ratio = 100;
|
* If off_t is only 32 bits, this allows calculations
|
||||||
if (beg_and_transferred < totalsize) {
|
* like (100 * transferred / totalsize) without risking overflow.
|
||||||
/* Do not update on every call
|
* Introduced error is < 0.1%
|
||||||
* (we can be called on every network read!) */
|
*/
|
||||||
if (since_last_update == 0)
|
kiloscale = 0;
|
||||||
return;
|
if (totalsize >= (1 << 20)) {
|
||||||
/* long long helps to have it working even if !LFS */
|
totalsize >>= 10;
|
||||||
ratio = 100ULL * beg_and_transferred / (uoff_t)totalsize;
|
beg_range >>= 10;
|
||||||
|
transferred >>= 10;
|
||||||
|
beg_and_transferred >>= 10;
|
||||||
|
kiloscale++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (beg_and_transferred >= totalsize)
|
||||||
|
beg_and_transferred = totalsize;
|
||||||
|
|
||||||
|
ratio = 100 * beg_and_transferred / totalsize;
|
||||||
#if ENABLE_UNICODE_SUPPORT
|
#if ENABLE_UNICODE_SUPPORT
|
||||||
init_unicode();
|
init_unicode();
|
||||||
{
|
{
|
||||||
@ -106,21 +116,20 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
|
|||||||
if (barlength > 0) {
|
if (barlength > 0) {
|
||||||
/* god bless gcc for variable arrays :) */
|
/* god bless gcc for variable arrays :) */
|
||||||
char buf[barlength + 1];
|
char buf[barlength + 1];
|
||||||
unsigned stars = (unsigned)barlength * ratio / (unsigned)100;
|
unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize;
|
||||||
memset(buf, ' ', barlength);
|
memset(buf, ' ', barlength);
|
||||||
buf[barlength] = '\0';
|
buf[barlength] = '\0';
|
||||||
memset(buf, '*', stars);
|
memset(buf, '*', stars);
|
||||||
fprintf(stderr, "|%s|", buf);
|
fprintf(stderr, "|%s|", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (beg_and_transferred >= 100000) {
|
while (beg_and_transferred >= 100000) {
|
||||||
i++;
|
kiloscale++;
|
||||||
beg_and_transferred >>= 10;
|
beg_and_transferred >>= 10;
|
||||||
}
|
}
|
||||||
/* see http://en.wikipedia.org/wiki/Tera */
|
/* see http://en.wikipedia.org/wiki/Tera */
|
||||||
fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[i]);
|
fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]);
|
||||||
#define beg_and_transferred dont_use_beg_and_transferred_below
|
#define beg_and_transferred dont_use_beg_and_transferred_below()
|
||||||
|
|
||||||
if (transferred > p->lastsize) {
|
if (transferred > p->lastsize) {
|
||||||
p->lastupdate_sec = elapsed;
|
p->lastupdate_sec = elapsed;
|
||||||
@ -137,13 +146,12 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
|
|||||||
if (since_last_update >= STALLTIME) {
|
if (since_last_update >= STALLTIME) {
|
||||||
fprintf(stderr, " - stalled -");
|
fprintf(stderr, " - stalled -");
|
||||||
} else {
|
} else {
|
||||||
off_t to_download = totalsize - beg_range;
|
uoff_t to_download = totalsize - beg_range;
|
||||||
if (!totalsize || transferred <= 0 || (int)elapsed <= 0 || transferred > to_download) {
|
if (!totalsize || (int)elapsed <= 0 || transferred > to_download) {
|
||||||
fprintf(stderr, "--:--:-- ETA");
|
fprintf(stderr, "--:--:-- ETA");
|
||||||
} else {
|
} else {
|
||||||
/* to_download / (transferred/elapsed) - elapsed: */
|
/* to_download / (transferred/elapsed) - elapsed: */
|
||||||
/* (long long helps to have working ETA even if !LFS) */
|
unsigned eta = to_download * elapsed / transferred - elapsed;
|
||||||
unsigned eta = (unsigned long long)to_download*elapsed/(uoff_t)transferred - elapsed;
|
|
||||||
unsigned secs = eta % 3600;
|
unsigned secs = eta % 3600;
|
||||||
unsigned hours = eta / 3600;
|
unsigned hours = eta / 3600;
|
||||||
fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60);
|
fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60);
|
||||||
|
Loading…
Reference in New Issue
Block a user