Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/openssh/src/progressmeter.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* $OpenBSD: progressmeter.c,v 1.45 2016/06/30 05:17:05 dtucker Exp $ */ | - | ||||||||||||
2 | /* | - | ||||||||||||
3 | * Copyright (c) 2003 Nils Nordman. All rights reserved. | - | ||||||||||||
4 | * | - | ||||||||||||
5 | * Redistribution and use in source and binary forms, with or without | - | ||||||||||||
6 | * modification, are permitted provided that the following conditions | - | ||||||||||||
7 | * are met: | - | ||||||||||||
8 | * 1. Redistributions of source code must retain the above copyright | - | ||||||||||||
9 | * notice, this list of conditions and the following disclaimer. | - | ||||||||||||
10 | * 2. Redistributions in binary form must reproduce the above copyright | - | ||||||||||||
11 | * notice, this list of conditions and the following disclaimer in the | - | ||||||||||||
12 | * documentation and/or other materials provided with the distribution. | - | ||||||||||||
13 | * | - | ||||||||||||
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | - | ||||||||||||
15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | - | ||||||||||||
16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | - | ||||||||||||
17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | - | ||||||||||||
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | - | ||||||||||||
19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | - | ||||||||||||
20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | - | ||||||||||||
21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | - | ||||||||||||
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | - | ||||||||||||
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | - | ||||||||||||
24 | */ | - | ||||||||||||
25 | - | |||||||||||||
26 | #include "includes.h" | - | ||||||||||||
27 | - | |||||||||||||
28 | #include <sys/types.h> | - | ||||||||||||
29 | #include <sys/ioctl.h> | - | ||||||||||||
30 | #include <sys/uio.h> | - | ||||||||||||
31 | - | |||||||||||||
32 | #include <errno.h> | - | ||||||||||||
33 | #include <signal.h> | - | ||||||||||||
34 | #include <stdio.h> | - | ||||||||||||
35 | #include <string.h> | - | ||||||||||||
36 | #include <time.h> | - | ||||||||||||
37 | #include <unistd.h> | - | ||||||||||||
38 | - | |||||||||||||
39 | #include "progressmeter.h" | - | ||||||||||||
40 | #include "atomicio.h" | - | ||||||||||||
41 | #include "misc.h" | - | ||||||||||||
42 | - | |||||||||||||
43 | #define DEFAULT_WINSIZE 80 | - | ||||||||||||
44 | #define MAX_WINSIZE 512 | - | ||||||||||||
45 | #define PADDING 1 /* padding between the progress indicators */ | - | ||||||||||||
46 | #define UPDATE_INTERVAL 1 /* update the progress meter every second */ | - | ||||||||||||
47 | #define STALL_TIME 5 /* we're stalled after this many seconds */ | - | ||||||||||||
48 | - | |||||||||||||
49 | /* determines whether we can output to the terminal */ | - | ||||||||||||
50 | static int can_output(void); | - | ||||||||||||
51 | - | |||||||||||||
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 */ | - | ||||||||||||
57 | static void sig_winch(int); | - | ||||||||||||
58 | static void setscreensize(void); | - | ||||||||||||
59 | - | |||||||||||||
60 | /* updates the progressmeter to reflect the current state of the transfer */ | - | ||||||||||||
61 | void refresh_progress_meter(void); | - | ||||||||||||
62 | - | |||||||||||||
63 | /* signal handler for updating the progress meter */ | - | ||||||||||||
64 | static void update_progress_meter(int); | - | ||||||||||||
65 | - | |||||||||||||
66 | static double start; /* start progress */ | - | ||||||||||||
67 | static double last_update; /* last progress update */ | - | ||||||||||||
68 | static const char *file; /* name of the file being transferred */ | - | ||||||||||||
69 | static off_t start_pos; /* initial position of transfer */ | - | ||||||||||||
70 | static off_t end_pos; /* ending position of transfer */ | - | ||||||||||||
71 | static off_t cur_pos; /* transfer position as of last refresh */ | - | ||||||||||||
72 | static volatile off_t *counter; /* progress counter */ | - | ||||||||||||
73 | static long stalled; /* how long we have been stalled */ | - | ||||||||||||
74 | static int bytes_per_second; /* current speed in bytes per second */ | - | ||||||||||||
75 | static int win_size; /* terminal window size */ | - | ||||||||||||
76 | static volatile sig_atomic_t win_resized; /* for window resizing */ | - | ||||||||||||
77 | - | |||||||||||||
78 | /* units for format_size */ | - | ||||||||||||
79 | static const char unit[] = " KMGT"; | - | ||||||||||||
80 | - | |||||||||||||
81 | static int | - | ||||||||||||
82 | can_output(void) | - | ||||||||||||
83 | { | - | ||||||||||||
84 | return (getpgrp() == tcgetpgrp(STDOUT_FILENO)); never executed: return (getpgrp() == tcgetpgrp( 1 )); | 0 | ||||||||||||
85 | } | - | ||||||||||||
86 | - | |||||||||||||
87 | static void | - | ||||||||||||
88 | format_rate(char *buf, int size, off_t bytes) | - | ||||||||||||
89 | { | - | ||||||||||||
90 | int i; | - | ||||||||||||
91 | - | |||||||||||||
92 | bytes *= 100; | - | ||||||||||||
93 | for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++)
| 0 | ||||||||||||
94 | bytes = (bytes + 512) / 1024; never executed: bytes = (bytes + 512) / 1024; | 0 | ||||||||||||
95 | if (i == 0) {
| 0 | ||||||||||||
96 | i++; | - | ||||||||||||
97 | bytes = (bytes + 512) / 1024; | - | ||||||||||||
98 | } never executed: end of block | 0 | ||||||||||||
99 | snprintf(buf, size, "%3lld.%1lld%c%s", | - | ||||||||||||
100 | (long long) (bytes + 5) / 100, | - | ||||||||||||
101 | (long long) (bytes + 5) / 10 % 10, | - | ||||||||||||
102 | unit[i], | - | ||||||||||||
103 | i ? "B" : " "); | - | ||||||||||||
104 | } never executed: end of block | 0 | ||||||||||||
105 | - | |||||||||||||
106 | static void | - | ||||||||||||
107 | format_size(char *buf, int size, off_t bytes) | - | ||||||||||||
108 | { | - | ||||||||||||
109 | int i; | - | ||||||||||||
110 | - | |||||||||||||
111 | for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++)
| 0 | ||||||||||||
112 | bytes = (bytes + 512) / 1024; never executed: bytes = (bytes + 512) / 1024; | 0 | ||||||||||||
113 | snprintf(buf, size, "%4lld%c%s", | - | ||||||||||||
114 | (long long) bytes, | - | ||||||||||||
115 | unit[i], | - | ||||||||||||
116 | i ? "B" : " "); | - | ||||||||||||
117 | } never executed: end of block | 0 | ||||||||||||
118 | - | |||||||||||||
119 | void | - | ||||||||||||
120 | refresh_progress_meter(void) | - | ||||||||||||
121 | { | - | ||||||||||||
122 | char buf[MAX_WINSIZE + 1]; | - | ||||||||||||
123 | off_t transferred; | - | ||||||||||||
124 | double elapsed, now; | - | ||||||||||||
125 | int percent; | - | ||||||||||||
126 | off_t bytes_left; | - | ||||||||||||
127 | int cur_speed; | - | ||||||||||||
128 | int hours, minutes, seconds; | - | ||||||||||||
129 | int i, len; | - | ||||||||||||
130 | int file_len; | - | ||||||||||||
131 | - | |||||||||||||
132 | transferred = *counter - (cur_pos ? cur_pos : start_pos);
| 0 | ||||||||||||
133 | cur_pos = *counter; | - | ||||||||||||
134 | now = monotime_double(); | - | ||||||||||||
135 | bytes_left = end_pos - cur_pos; | - | ||||||||||||
136 | - | |||||||||||||
137 | if (bytes_left > 0)
| 0 | ||||||||||||
138 | elapsed = now - last_update; never executed: elapsed = now - last_update; | 0 | ||||||||||||
139 | else { | - | ||||||||||||
140 | elapsed = now - start; | - | ||||||||||||
141 | /* Calculate true total speed when done */ | - | ||||||||||||
142 | transferred = end_pos - start_pos; | - | ||||||||||||
143 | bytes_per_second = 0; | - | ||||||||||||
144 | } never executed: end of block | 0 | ||||||||||||
145 | - | |||||||||||||
146 | /* calculate speed */ | - | ||||||||||||
147 | if (elapsed != 0)
| 0 | ||||||||||||
148 | cur_speed = (transferred / elapsed); never executed: cur_speed = (transferred / elapsed); | 0 | ||||||||||||
149 | else | - | ||||||||||||
150 | cur_speed = transferred; never executed: cur_speed = transferred; | 0 | ||||||||||||
151 | - | |||||||||||||
152 | #define AGE_FACTOR 0.9 | - | ||||||||||||
153 | if (bytes_per_second != 0) {
| 0 | ||||||||||||
154 | bytes_per_second = (bytes_per_second * AGE_FACTOR) + | - | ||||||||||||
155 | (cur_speed * (1.0 - AGE_FACTOR)); | - | ||||||||||||
156 | } else never executed: end of block | 0 | ||||||||||||
157 | bytes_per_second = cur_speed; never executed: bytes_per_second = cur_speed; | 0 | ||||||||||||
158 | - | |||||||||||||
159 | /* filename */ | - | ||||||||||||
160 | buf[0] = '\0'; | - | ||||||||||||
161 | file_len = win_size - 35; | - | ||||||||||||
162 | if (file_len > 0) {
| 0 | ||||||||||||
163 | len = snprintf(buf, file_len + 1, "\r%s", file); | - | ||||||||||||
164 | if (len < 0)
| 0 | ||||||||||||
165 | len = 0; never executed: len = 0; | 0 | ||||||||||||
166 | if (len >= file_len + 1)
| 0 | ||||||||||||
167 | len = file_len; never executed: len = file_len; | 0 | ||||||||||||
168 | for (i = len; i < file_len; i++)
| 0 | ||||||||||||
169 | buf[i] = ' '; never executed: buf[i] = ' '; | 0 | ||||||||||||
170 | buf[file_len] = '\0'; | - | ||||||||||||
171 | } never executed: end of block | 0 | ||||||||||||
172 | - | |||||||||||||
173 | /* percent of transfer done */ | - | ||||||||||||
174 | if (end_pos == 0 || cur_pos == end_pos)
| 0 | ||||||||||||
175 | percent = 100; never executed: percent = 100; | 0 | ||||||||||||
176 | else | - | ||||||||||||
177 | percent = ((float)cur_pos / end_pos) * 100; never executed: percent = ((float)cur_pos / end_pos) * 100; | 0 | ||||||||||||
178 | snprintf(buf + strlen(buf), win_size - strlen(buf), | - | ||||||||||||
179 | " %3d%% ", percent); | - | ||||||||||||
180 | - | |||||||||||||
181 | /* amount transferred */ | - | ||||||||||||
182 | format_size(buf + strlen(buf), win_size - strlen(buf), | - | ||||||||||||
183 | cur_pos); | - | ||||||||||||
184 | strlcat(buf, " ", win_size); | - | ||||||||||||
185 | - | |||||||||||||
186 | /* bandwidth usage */ | - | ||||||||||||
187 | format_rate(buf + strlen(buf), win_size - strlen(buf), | - | ||||||||||||
188 | (off_t)bytes_per_second); | - | ||||||||||||
189 | strlcat(buf, "/s ", win_size); | - | ||||||||||||
190 | - | |||||||||||||
191 | /* ETA */ | - | ||||||||||||
192 | if (!transferred)
| 0 | ||||||||||||
193 | stalled += elapsed; never executed: stalled += elapsed; | 0 | ||||||||||||
194 | else | - | ||||||||||||
195 | stalled = 0; never executed: stalled = 0; | 0 | ||||||||||||
196 | - | |||||||||||||
197 | if (stalled >= STALL_TIME)
| 0 | ||||||||||||
198 | strlcat(buf, "- stalled -", win_size); never executed: strlcat(buf, "- stalled -", win_size); | 0 | ||||||||||||
199 | else if (bytes_per_second == 0 && bytes_left)
| 0 | ||||||||||||
200 | strlcat(buf, " --:-- ETA", win_size); never executed: strlcat(buf, " --:-- ETA", win_size); | 0 | ||||||||||||
201 | else { | - | ||||||||||||
202 | if (bytes_left > 0)
| 0 | ||||||||||||
203 | seconds = bytes_left / bytes_per_second; never executed: seconds = bytes_left / bytes_per_second; | 0 | ||||||||||||
204 | else | - | ||||||||||||
205 | seconds = elapsed; never executed: seconds = elapsed; | 0 | ||||||||||||
206 | - | |||||||||||||
207 | hours = seconds / 3600; | - | ||||||||||||
208 | seconds -= hours * 3600; | - | ||||||||||||
209 | minutes = seconds / 60; | - | ||||||||||||
210 | seconds -= minutes * 60; | - | ||||||||||||
211 | - | |||||||||||||
212 | if (hours != 0)
| 0 | ||||||||||||
213 | snprintf(buf + strlen(buf), win_size - strlen(buf), never executed: snprintf(buf + strlen(buf), win_size - strlen(buf), "%d:%02d:%02d", hours, minutes, seconds); | 0 | ||||||||||||
214 | "%d:%02d:%02d", hours, minutes, seconds); never executed: snprintf(buf + strlen(buf), win_size - strlen(buf), "%d:%02d:%02d", hours, minutes, seconds); | 0 | ||||||||||||
215 | else | - | ||||||||||||
216 | snprintf(buf + strlen(buf), win_size - strlen(buf), never executed: snprintf(buf + strlen(buf), win_size - strlen(buf), " %02d:%02d", minutes, seconds); | 0 | ||||||||||||
217 | " %02d:%02d", minutes, seconds); never executed: snprintf(buf + strlen(buf), win_size - strlen(buf), " %02d:%02d", minutes, seconds); | 0 | ||||||||||||
218 | - | |||||||||||||
219 | if (bytes_left > 0)
| 0 | ||||||||||||
220 | strlcat(buf, " ETA", win_size); never executed: strlcat(buf, " ETA", win_size); | 0 | ||||||||||||
221 | else | - | ||||||||||||
222 | strlcat(buf, " ", win_size); never executed: strlcat(buf, " ", win_size); | 0 | ||||||||||||
223 | } | - | ||||||||||||
224 | - | |||||||||||||
225 | atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); | - | ||||||||||||
226 | last_update = now; | - | ||||||||||||
227 | } never executed: end of block | 0 | ||||||||||||
228 | - | |||||||||||||
229 | /*ARGSUSED*/ | - | ||||||||||||
230 | static void | - | ||||||||||||
231 | update_progress_meter(int ignore) | - | ||||||||||||
232 | { | - | ||||||||||||
233 | int save_errno; | - | ||||||||||||
234 | - | |||||||||||||
235 | save_errno = errno; | - | ||||||||||||
236 | - | |||||||||||||
237 | if (win_resized) {
| 0 | ||||||||||||
238 | setscreensize(); | - | ||||||||||||
239 | win_resized = 0; | - | ||||||||||||
240 | } never executed: end of block | 0 | ||||||||||||
241 | if (can_output())
| 0 | ||||||||||||
242 | refresh_progress_meter(); never executed: refresh_progress_meter(); | 0 | ||||||||||||
243 | - | |||||||||||||
244 | signal(SIGALRM, update_progress_meter); | - | ||||||||||||
245 | alarm(UPDATE_INTERVAL); | - | ||||||||||||
246 | errno = save_errno; | - | ||||||||||||
247 | } never executed: end of block | 0 | ||||||||||||
248 | - | |||||||||||||
249 | void | - | ||||||||||||
250 | start_progress_meter(const char *f, off_t filesize, off_t *ctr) | - | ||||||||||||
251 | { | - | ||||||||||||
252 | start = last_update = monotime_double(); | - | ||||||||||||
253 | file = f; | - | ||||||||||||
254 | start_pos = *ctr; | - | ||||||||||||
255 | end_pos = filesize; | - | ||||||||||||
256 | cur_pos = 0; | - | ||||||||||||
257 | counter = ctr; | - | ||||||||||||
258 | stalled = 0; | - | ||||||||||||
259 | bytes_per_second = 0; | - | ||||||||||||
260 | - | |||||||||||||
261 | setscreensize(); | - | ||||||||||||
262 | if (can_output())
| 0 | ||||||||||||
263 | refresh_progress_meter(); never executed: refresh_progress_meter(); | 0 | ||||||||||||
264 | - | |||||||||||||
265 | signal(SIGALRM, update_progress_meter); | - | ||||||||||||
266 | signal(SIGWINCH, sig_winch); | - | ||||||||||||
267 | alarm(UPDATE_INTERVAL); | - | ||||||||||||
268 | } never executed: end of block | 0 | ||||||||||||
269 | - | |||||||||||||
270 | void | - | ||||||||||||
271 | stop_progress_meter(void) | - | ||||||||||||
272 | { | - | ||||||||||||
273 | alarm(0); | - | ||||||||||||
274 | - | |||||||||||||
275 | if (!can_output())
| 0 | ||||||||||||
276 | return; never executed: return; | 0 | ||||||||||||
277 | - | |||||||||||||
278 | /* Ensure we complete the progress */ | - | ||||||||||||
279 | if (cur_pos != end_pos)
| 0 | ||||||||||||
280 | refresh_progress_meter(); never executed: refresh_progress_meter(); | 0 | ||||||||||||
281 | - | |||||||||||||
282 | atomicio(vwrite, STDOUT_FILENO, "\n", 1); | - | ||||||||||||
283 | } never executed: end of block | 0 | ||||||||||||
284 | - | |||||||||||||
285 | /*ARGSUSED*/ | - | ||||||||||||
286 | static void | - | ||||||||||||
287 | sig_winch(int sig) | - | ||||||||||||
288 | { | - | ||||||||||||
289 | win_resized = 1; | - | ||||||||||||
290 | } never executed: end of block | 0 | ||||||||||||
291 | - | |||||||||||||
292 | static void | - | ||||||||||||
293 | setscreensize(void) | - | ||||||||||||
294 | { | - | ||||||||||||
295 | struct winsize winsize; | - | ||||||||||||
296 | - | |||||||||||||
297 | if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 &&
| 0 | ||||||||||||
298 | winsize.ws_col != 0) {
| 0 | ||||||||||||
299 | if (winsize.ws_col > MAX_WINSIZE)
| 0 | ||||||||||||
300 | win_size = MAX_WINSIZE; never executed: win_size = 512; | 0 | ||||||||||||
301 | else | - | ||||||||||||
302 | win_size = winsize.ws_col; never executed: win_size = winsize.ws_col; | 0 | ||||||||||||
303 | } else | - | ||||||||||||
304 | win_size = DEFAULT_WINSIZE; never executed: win_size = 80; | 0 | ||||||||||||
305 | win_size += 1; /* trailing \0 */ | - | ||||||||||||
306 | } never executed: end of block | 0 | ||||||||||||
Source code | Switch to Preprocessed file |