Bump to version 1.22.1
[platform/upstream/busybox.git] / libbb / progress.c
index a490b83..372feb0 100644 (file)
@@ -52,12 +52,18 @@ static unsigned int get_tty2_width(void)
        return width;
 }
 
-void FAST_FUNC bb_progress_init(bb_progress_t *p)
+void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile)
 {
+#if ENABLE_UNICODE_SUPPORT
+       init_unicode();
+       p->curfile = unicode_conv_to_printable_fixedwidth(/*NULL,*/ curfile, 20);
+#else
+       p->curfile = curfile;
+#endif
        p->start_sec = monotonic_sec();
-       p->lastupdate_sec = p->start_sec;
-       p->lastsize = 0;
-       p->inited = 1;
+       p->last_update_sec = p->start_sec;
+       p->last_change_sec = p->start_sec;
+       p->last_size = 0;
 }
 
 /* File already had beg_size bytes.
@@ -68,27 +74,33 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p)
  * If totalsize == 0, then it is unknown.
  */
 void FAST_FUNC bb_progress_update(bb_progress_t *p,
-               const char *curfile,
                uoff_t beg_size,
                uoff_t transferred,
                uoff_t totalsize)
 {
        uoff_t beg_and_transferred;
        unsigned since_last_update, elapsed;
-       unsigned ratio;
        int barlength;
        int kiloscale;
 
-       beg_and_transferred = beg_size + transferred;
+       //transferred = 1234; /* use for stall detection testing */
+       //totalsize = 0; /* use for unknown size download testing */
 
        elapsed = monotonic_sec();
-       since_last_update = elapsed - p->lastupdate_sec;
-       /*
-        * Do not update on every call
-        * (we can be called on every network read!)
-        */
-       if (since_last_update == 0 && beg_and_transferred < totalsize)
+       since_last_update = elapsed - p->last_update_sec;
+       p->last_update_sec = elapsed;
+
+       if (totalsize != 0 && transferred >= totalsize - beg_size) {
+               /* Last call. Do not skip this update */
+               transferred = totalsize - beg_size; /* sanitize just in case */
+       }
+       else if (since_last_update == 0) {
+               /*
+                * Do not update on every call
+                * (we can be called on every network read!)
+                */
                return;
+       }
 
        kiloscale = 0;
        /*
@@ -101,54 +113,51 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
                /*
                 * 64-bit CPU || small off_t: in either case,
                 * >> is cheap, single-word operation.
-                * ... || strange off_t: also use this code (it is safe,
-                * even if suboptimal), because 32/64 optimized one
-                * works only for 64-bit off_t.
+                * ... || strange off_t: also use this code
+                * (it is safe, just suboptimal wrt code size),
+                * because 32/64 optimized one works only for 64-bit off_t.
                 */
                if (totalsize >= (1 << 22)) {
                        totalsize >>= 10;
                        beg_size >>= 10;
                        transferred >>= 10;
-                       beg_and_transferred >>= 10;
                        kiloscale = 1;
                }
        } else {
                /* 32-bit CPU and 64-bit off_t.
-                * Pick a shift (40 bits) which is easier to do on 32-bit CPU.
+                * Use a 40-bit shift, it is easier to do on 32-bit CPU.
                 */
-               if (totalsize >= (uoff_t)(1ULL << 54)) {
-                       totalsize = (uint32_t)(totalsize >> 32) >> 8;
-                       beg_size = (uint32_t)(beg_size >> 32) >> 8;
-                       transferred = (uint32_t)(transferred >> 32) >> 8;
-                       beg_and_transferred = (uint32_t)(beg_and_transferred >> 32) >> 8;
+/* ONE suppresses "warning: shift count >= width of type" */
+#define ONE (sizeof(off_t) > 4)
+               if (totalsize >= (uoff_t)(1ULL << 54*ONE)) {
+                       totalsize = (uint32_t)(totalsize >> 32*ONE) >> 8;
+                       beg_size = (uint32_t)(beg_size >> 32*ONE) >> 8;
+                       transferred = (uint32_t)(transferred >> 32*ONE) >> 8;
                        kiloscale = 4;
                }
        }
 
-       if (beg_and_transferred > totalsize)
-               beg_and_transferred = totalsize;
+       if (ENABLE_UNICODE_SUPPORT)
+               fprintf(stderr, "\r%s", p->curfile);
+       else
+               fprintf(stderr, "\r%-20.20s", p->curfile);
 
-       ratio = 100 * beg_and_transferred / totalsize;
-#if ENABLE_UNICODE_SUPPORT
-       init_unicode();
-       {
-               char *buf = unicode_conv_to_printable_fixedwidth(/*NULL,*/ curfile, 20);
-               fprintf(stderr, "\r%s%4u%% ", buf, ratio);
-               free(buf);
-       }
-#else
-       fprintf(stderr, "\r%-20.20s%4u%% ", curfile, ratio);
-#endif
+       beg_and_transferred = beg_size + transferred;
 
-       barlength = get_tty2_width() - 49;
-       if (barlength > 0) {
-               /* god bless gcc for variable arrays :) */
-               char buf[barlength + 1];
-               unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize;
-               memset(buf, ' ', barlength);
-               buf[barlength] = '\0';
-               memset(buf, '*', stars);
-               fprintf(stderr, "|%s|", buf);
+       if (totalsize != 0) {
+               unsigned ratio = 100 * beg_and_transferred / totalsize;
+               fprintf(stderr, "%4u%%", ratio);
+
+               barlength = get_tty2_width() - 49;
+               if (barlength > 0) {
+                       /* god bless gcc for variable arrays :) */
+                       char buf[barlength + 1];
+                       unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize;
+                       memset(buf, ' ', barlength);
+                       buf[barlength] = '\0';
+                       memset(buf, '*', stars);
+                       fprintf(stderr, " |%s|", buf);
+               }
        }
 
        while (beg_and_transferred >= 100000) {
@@ -156,14 +165,15 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
                kiloscale++;
        }
        /* see http://en.wikipedia.org/wiki/Tera */
-       fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]);
+       fprintf(stderr, "%6u%c", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]);
 #define beg_and_transferred dont_use_beg_and_transferred_below()
 
-       if (transferred != p->lastsize) {
-               p->lastupdate_sec = elapsed;
-               p->lastsize = transferred;
+       since_last_update = elapsed - p->last_change_sec;
+       if ((unsigned)transferred != p->last_size) {
+               p->last_change_sec = elapsed;
+               p->last_size = (unsigned)transferred;
                if (since_last_update >= STALLTIME) {
-                       /* We "cut off" these seconds from elapsed time
+                       /* We "cut out" these seconds from elapsed time
                         * by adjusting start time */
                        p->start_sec += since_last_update;
                }
@@ -173,9 +183,9 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
        elapsed -= p->start_sec; /* now it's "elapsed since start" */
 
        if (since_last_update >= STALLTIME) {
-               fprintf(stderr, " - stalled -");
-       } else if (!totalsize || !transferred || (int)elapsed <= 0) {
-               fprintf(stderr, "--:--:-- ETA");
+               fprintf(stderr, "  - stalled -");
+       } else if (!totalsize || !transferred || (int)elapsed < 0) {
+               fprintf(stderr, " --:--:-- ETA");
        } else {
                unsigned eta, secs, hours;
 
@@ -188,8 +198,10 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
                 * totalsize * elapsed / transferred - elapsed
                 */
                eta = totalsize * elapsed / transferred - elapsed;
+               if (eta >= 1000*60*60)
+                       eta = 1000*60*60 - 1;
                secs = eta % 3600;
                hours = eta / 3600;
-               fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60);
+               fprintf(stderr, "%3u:%02u:%02u ETA", hours, secs / 60, secs % 60);
        }
 }