|
Lines 28-35
Link Here
|
| 28 |
#include <sys/uio.h> |
28 |
#include <sys/uio.h> |
| 29 |
|
29 |
|
| 30 |
#include <errno.h> |
30 |
#include <errno.h> |
|
|
31 |
#include <limits.h> |
| 32 |
#include <signal.h> |
| 31 |
#include <signal.h> |
33 |
#include <signal.h> |
| 32 |
#include <stdarg.h> |
34 |
#include <stdarg.h> |
|
|
35 |
#include <stdlib.h> |
| 33 |
#include <stdio.h> |
36 |
#include <stdio.h> |
| 34 |
#include <string.h> |
37 |
#include <string.h> |
| 35 |
#include <time.h> |
38 |
#include <time.h> |
|
Lines 49-58
Link Here
|
| 49 |
/* determines whether we can output to the terminal */ |
52 |
/* determines whether we can output to the terminal */ |
| 50 |
static int can_output(void); |
53 |
static int can_output(void); |
| 51 |
|
54 |
|
| 52 |
/* formats and inserts the specified size into the given buffer */ |
|
|
| 53 |
static void format_size(char *, int, off_t); |
| 54 |
static void format_rate(char *, int, off_t); |
| 55 |
|
| 56 |
/* window resizing */ |
55 |
/* window resizing */ |
| 57 |
static void sig_winch(int); |
56 |
static void sig_winch(int); |
| 58 |
static void setscreensize(void); |
57 |
static void setscreensize(void); |
|
Lines 82-91
can_output(void)
Link Here
|
| 82 |
return (getpgrp() == tcgetpgrp(STDOUT_FILENO)); |
81 |
return (getpgrp() == tcgetpgrp(STDOUT_FILENO)); |
| 83 |
} |
82 |
} |
| 84 |
|
83 |
|
| 85 |
static void |
84 |
/* size needed to format integer type v, using (nbits(v) * log2(10) / 10) */ |
| 86 |
format_rate(char *buf, int size, off_t bytes) |
85 |
#define STRING_SIZE(v) (((sizeof(v) * 8 * 4) / 10) + 1) |
|
|
86 |
|
| 87 |
static const char * |
| 88 |
format_rate(off_t bytes) |
| 87 |
{ |
89 |
{ |
| 88 |
int i; |
90 |
int i; |
|
|
91 |
static char buf[STRING_SIZE(bytes) * 2 + 16]; |
| 89 |
|
92 |
|
| 90 |
bytes *= 100; |
93 |
bytes *= 100; |
| 91 |
for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++) |
94 |
for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++) |
|
Lines 94-130
format_rate(char *buf, int size, off_t bytes)
Link Here
|
| 94 |
i++; |
97 |
i++; |
| 95 |
bytes = (bytes + 512) / 1024; |
98 |
bytes = (bytes + 512) / 1024; |
| 96 |
} |
99 |
} |
| 97 |
snprintf(buf, size, "%3lld.%1lld%c%s", |
100 |
snprintf(buf, sizeof(buf), "%3lld.%1lld%c%s", |
| 98 |
(long long) (bytes + 5) / 100, |
101 |
(long long) (bytes + 5) / 100, |
| 99 |
(long long) (bytes + 5) / 10 % 10, |
102 |
(long long) (bytes + 5) / 10 % 10, |
| 100 |
unit[i], |
103 |
unit[i], |
| 101 |
i ? "B" : " "); |
104 |
i ? "B" : " "); |
|
|
105 |
return buf; |
| 102 |
} |
106 |
} |
| 103 |
|
107 |
|
| 104 |
static void |
108 |
static const char * |
| 105 |
format_size(char *buf, int size, off_t bytes) |
109 |
format_size(off_t bytes) |
| 106 |
{ |
110 |
{ |
| 107 |
int i; |
111 |
int i; |
|
|
112 |
static char buf[STRING_SIZE(bytes) + 16]; |
| 108 |
|
113 |
|
| 109 |
for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++) |
114 |
for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++) |
| 110 |
bytes = (bytes + 512) / 1024; |
115 |
bytes = (bytes + 512) / 1024; |
| 111 |
snprintf(buf, size, "%4lld%c%s", |
116 |
snprintf(buf, sizeof(buf), "%4lld%c%s", |
| 112 |
(long long) bytes, |
117 |
(long long) bytes, |
| 113 |
unit[i], |
118 |
unit[i], |
| 114 |
i ? "B" : " "); |
119 |
i ? "B" : " "); |
|
|
120 |
return buf; |
| 115 |
} |
121 |
} |
| 116 |
|
122 |
|
| 117 |
void |
123 |
void |
| 118 |
refresh_progress_meter(int force_update) |
124 |
refresh_progress_meter(int force_update) |
| 119 |
{ |
125 |
{ |
| 120 |
char buf[MAX_WINSIZE + 1]; |
126 |
char *buf = NULL, *obuf = NULL; |
| 121 |
off_t transferred; |
127 |
off_t transferred; |
| 122 |
double elapsed, now; |
128 |
double elapsed, now; |
| 123 |
int percent; |
129 |
int percent; |
| 124 |
off_t bytes_left; |
130 |
off_t bytes_left; |
| 125 |
int cur_speed; |
131 |
int cur_speed; |
| 126 |
int hours, minutes, seconds; |
132 |
int hours, minutes, seconds; |
| 127 |
int file_len; |
133 |
int file_len, cols; |
| 128 |
|
134 |
|
| 129 |
if ((!force_update && !alarm_fired && !win_resized) || !can_output()) |
135 |
if ((!force_update && !alarm_fired && !win_resized) || !can_output()) |
| 130 |
return; |
136 |
return; |
|
Lines 162-193
refresh_progress_meter(int force_update)
Link Here
|
| 162 |
} else |
168 |
} else |
| 163 |
bytes_per_second = cur_speed; |
169 |
bytes_per_second = cur_speed; |
| 164 |
|
170 |
|
|
|
171 |
last_update = now; |
| 172 |
|
| 173 |
/* Don't bother if we can't even display the completion percentage */ |
| 174 |
if (win_size < 4) |
| 175 |
return; |
| 176 |
|
| 165 |
/* filename */ |
177 |
/* filename */ |
| 166 |
buf[0] = '\0'; |
178 |
file_len = cols = win_size - 36; |
| 167 |
file_len = win_size - 36; |
|
|
| 168 |
if (file_len > 0) { |
179 |
if (file_len > 0) { |
| 169 |
buf[0] = '\r'; |
180 |
asmprintf(&buf, INT_MAX, &cols, "%-*s", file_len, file); |
| 170 |
snmprintf(buf+1, sizeof(buf)-1, &file_len, "%-*s", |
181 |
/* If we used fewer columns than expected then pad */ |
| 171 |
file_len, file); |
182 |
if (cols < file_len) |
|
|
183 |
xextendf(&buf, NULL, "%*s", file_len - cols, ""); |
| 172 |
} |
184 |
} |
| 173 |
|
|
|
| 174 |
/* percent of transfer done */ |
185 |
/* percent of transfer done */ |
| 175 |
if (end_pos == 0 || cur_pos == end_pos) |
186 |
if (end_pos == 0 || cur_pos == end_pos) |
| 176 |
percent = 100; |
187 |
percent = 100; |
| 177 |
else |
188 |
else |
| 178 |
percent = ((float)cur_pos / end_pos) * 100; |
189 |
percent = ((float)cur_pos / end_pos) * 100; |
| 179 |
snprintf(buf + strlen(buf), win_size - strlen(buf), |
|
|
| 180 |
" %3d%% ", percent); |
| 181 |
|
190 |
|
| 182 |
/* amount transferred */ |
191 |
/* percent / amount transferred / bandwidth usage */ |
| 183 |
format_size(buf + strlen(buf), win_size - strlen(buf), |
192 |
xextendf(&buf, NULL, " %3d%% %s %s/s ", percent, format_size(cur_pos), |
| 184 |
cur_pos); |
193 |
format_rate((off_t)bytes_per_second)); |
| 185 |
strlcat(buf, " ", win_size); |
|
|
| 186 |
|
| 187 |
/* bandwidth usage */ |
| 188 |
format_rate(buf + strlen(buf), win_size - strlen(buf), |
| 189 |
(off_t)bytes_per_second); |
| 190 |
strlcat(buf, "/s ", win_size); |
| 191 |
|
194 |
|
| 192 |
/* ETA */ |
195 |
/* ETA */ |
| 193 |
if (!transferred) |
196 |
if (!transferred) |
|
Lines 196-204
refresh_progress_meter(int force_update)
Link Here
|
| 196 |
stalled = 0; |
199 |
stalled = 0; |
| 197 |
|
200 |
|
| 198 |
if (stalled >= STALL_TIME) |
201 |
if (stalled >= STALL_TIME) |
| 199 |
strlcat(buf, "- stalled -", win_size); |
202 |
xextendf(&buf, NULL, "- stalled -"); |
| 200 |
else if (bytes_per_second == 0 && bytes_left) |
203 |
else if (bytes_per_second == 0 && bytes_left) |
| 201 |
strlcat(buf, " --:-- ETA", win_size); |
204 |
xextendf(&buf, NULL, " --:-- ETA"); |
| 202 |
else { |
205 |
else { |
| 203 |
if (bytes_left > 0) |
206 |
if (bytes_left > 0) |
| 204 |
seconds = bytes_left / bytes_per_second; |
207 |
seconds = bytes_left / bytes_per_second; |
|
Lines 210-230
refresh_progress_meter(int force_update)
Link Here
|
| 210 |
minutes = seconds / 60; |
213 |
minutes = seconds / 60; |
| 211 |
seconds -= minutes * 60; |
214 |
seconds -= minutes * 60; |
| 212 |
|
215 |
|
| 213 |
if (hours != 0) |
216 |
if (hours != 0) { |
| 214 |
snprintf(buf + strlen(buf), win_size - strlen(buf), |
217 |
xextendf(&buf, NULL, "%d:%02d:%02d", |
| 215 |
"%d:%02d:%02d", hours, minutes, seconds); |
218 |
hours, minutes, seconds); |
| 216 |
else |
219 |
} else |
| 217 |
snprintf(buf + strlen(buf), win_size - strlen(buf), |
220 |
xextendf(&buf, NULL, " %02d:%02d", minutes, seconds); |
| 218 |
" %02d:%02d", minutes, seconds); |
|
|
| 219 |
|
221 |
|
| 220 |
if (bytes_left > 0) |
222 |
if (bytes_left > 0) |
| 221 |
strlcat(buf, " ETA", win_size); |
223 |
xextendf(&buf, NULL, " ETA"); |
| 222 |
else |
224 |
else |
| 223 |
strlcat(buf, " ", win_size); |
225 |
xextendf(&buf, NULL, " "); |
| 224 |
} |
226 |
} |
| 225 |
|
227 |
|
| 226 |
atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); |
228 |
/* Finally, truncate string at window width */ |
| 227 |
last_update = now; |
229 |
cols = win_size - 1; |
|
|
230 |
asmprintf(&obuf, INT_MAX, &cols, " %s", buf); |
| 231 |
if (obuf != NULL) { |
| 232 |
*obuf = '\r'; /* must insert as asmprintf() would escape it */ |
| 233 |
atomicio(vwrite, STDOUT_FILENO, obuf, strlen(obuf)); |
| 234 |
} |
| 235 |
free(buf); |
| 236 |
free(obuf); |
| 228 |
} |
237 |
} |
| 229 |
|
238 |
|
| 230 |
/*ARGSUSED*/ |
239 |
/*ARGSUSED*/ |