1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40#include "libbb.h"
41#include "unicode.h"
42
43enum {
44
45 STALLTIME = 5
46};
47
48static unsigned int get_tty2_width(void)
49{
50 unsigned width;
51 get_terminal_width_height(2, &width, NULL);
52 return width;
53}
54
55void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile)
56{
57#if ENABLE_UNICODE_SUPPORT
58 init_unicode();
59 p->curfile = unicode_conv_to_printable_fixedwidth( curfile, 20);
60#else
61 p->curfile = curfile;
62#endif
63 p->start_sec = monotonic_sec();
64 p->last_update_sec = p->start_sec;
65 p->last_change_sec = p->start_sec;
66 p->last_size = 0;
67}
68
69
70
71
72
73
74
75
76void FAST_FUNC bb_progress_update(bb_progress_t *p,
77 uoff_t beg_size,
78 uoff_t transferred,
79 uoff_t totalsize)
80{
81 uoff_t beg_and_transferred;
82 unsigned since_last_update, elapsed;
83 int barlength;
84 int kiloscale;
85
86
87
88
89 elapsed = monotonic_sec();
90 since_last_update = elapsed - p->last_update_sec;
91 p->last_update_sec = elapsed;
92
93 if (totalsize != 0 && transferred >= totalsize - beg_size) {
94
95 transferred = totalsize - beg_size;
96 }
97 else if (since_last_update == 0) {
98
99
100
101
102 return;
103 }
104
105 kiloscale = 0;
106
107
108
109
110
111
112 if (ULONG_MAX > 0xffffffff || sizeof(off_t) == 4 || sizeof(off_t) != 8) {
113
114
115
116
117
118
119
120 if (totalsize >= (1 << 22)) {
121 totalsize >>= 10;
122 beg_size >>= 10;
123 transferred >>= 10;
124 kiloscale = 1;
125 }
126 } else {
127
128
129
130
131#define ONE (sizeof(off_t) > 4)
132 if (totalsize >= (uoff_t)(1ULL << 54*ONE)) {
133 totalsize = (uint32_t)(totalsize >> 32*ONE) >> 8;
134 beg_size = (uint32_t)(beg_size >> 32*ONE) >> 8;
135 transferred = (uint32_t)(transferred >> 32*ONE) >> 8;
136 kiloscale = 4;
137 }
138 }
139
140 if (ENABLE_UNICODE_SUPPORT)
141 fprintf(stderr, "\r%s", p->curfile);
142 else
143 fprintf(stderr, "\r%-20.20s", p->curfile);
144
145 beg_and_transferred = beg_size + transferred;
146
147 if (totalsize != 0) {
148 unsigned ratio = 100 * beg_and_transferred / totalsize;
149 fprintf(stderr, "%4u%%", ratio);
150
151 barlength = get_tty2_width() - 49;
152 if (barlength > 0) {
153
154 char buf[barlength + 1];
155 unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize;
156 memset(buf, ' ', barlength);
157 buf[barlength] = '\0';
158 memset(buf, '*', stars);
159 fprintf(stderr, " |%s|", buf);
160 }
161 }
162
163 while (beg_and_transferred >= 100000) {
164 beg_and_transferred >>= 10;
165 kiloscale++;
166 }
167
168 fprintf(stderr, "%6u%c", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]);
169#define beg_and_transferred dont_use_beg_and_transferred_below()
170
171 since_last_update = elapsed - p->last_change_sec;
172 if ((unsigned)transferred != p->last_size) {
173 p->last_change_sec = elapsed;
174 p->last_size = (unsigned)transferred;
175 if (since_last_update >= STALLTIME) {
176
177
178 p->start_sec += since_last_update;
179 }
180 since_last_update = 0;
181 }
182
183 elapsed -= p->start_sec;
184
185 if (since_last_update >= STALLTIME) {
186 fprintf(stderr, " - stalled -");
187 } else if (!totalsize || !transferred || (int)elapsed < 0) {
188 fprintf(stderr, " --:--:-- ETA");
189 } else {
190 unsigned eta, secs, hours;
191
192 totalsize -= beg_size;
193
194
195
196
197
198
199
200 eta = totalsize * elapsed / transferred - elapsed;
201 if (eta >= 1000*60*60)
202 eta = 1000*60*60 - 1;
203 secs = eta % 3600;
204 hours = eta / 3600;
205 fprintf(stderr, "%3u:%02u:%02u ETA", hours, secs / 60, secs % 60);
206 }
207}
208