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