]>
Commit | Line | Data |
---|---|---|
dbfc1835 | 1 | diff -ru coreutils-8.4.orig/src/copy.c coreutils-8.4/src/copy.c |
2 | --- coreutils-8.4.orig/src/copy.c 2010-01-25 16:03:29.606930239 +0100 | |
f2e36e57 | 3 | +++ coreutils-8.4/src/copy.c 2010-01-26 15:37:24.544158220 +0100 |
dbfc1835 | 4 | @@ -457,6 +457,56 @@ |
5 | return lchmod (name, mode); | |
6 | } | |
7 | ||
8 | +/* BEGIN progress mod */ | |
9 | +static void file_progress_bar ( char * _cDest, int _iBarLength, int _iProgress, int _iTotal ) | |
10 | +{ | |
11 | + // write number to progress bar | |
12 | + float fPercent = ( float ) _iProgress / ( float ) _iTotal * 100.f; | |
13 | + sprintf ( _cDest + ( _iBarLength - 6 ), "%4.1f", fPercent ); | |
14 | + // remove zero | |
15 | + _cDest[_iBarLength - 2] = ' '; | |
f2e36e57 | 16 | + |
dbfc1835 | 17 | + // fill rest with '-' |
18 | + int i; | |
19 | + for ( i = 1; i <= _iBarLength - 9; i++ ) | |
20 | + { | |
21 | + if ( fPercent > ( float ) ( i - 1 ) / ( _iBarLength - 10 ) * 100.f ) | |
22 | + _cDest[i] = '|'; | |
23 | + else | |
24 | + _cDest[i] = '-'; | |
25 | + } | |
26 | +} | |
27 | + | |
28 | +int file_size_format ( char * _cDst, int _iSize, int _iCounter ) | |
29 | +{ | |
30 | + int iCounter = _iCounter; | |
31 | + double dSize = ( double ) _iSize; | |
32 | + while ( dSize >= 1000. ) | |
33 | + { | |
34 | + dSize /= 1024.; | |
35 | + iCounter++; | |
36 | + } | |
f2e36e57 | 37 | + |
dbfc1835 | 38 | + /* get unit */ |
39 | + char * sUnit; | |
40 | + if ( iCounter == 0 ) | |
41 | + sUnit = "B"; | |
42 | + else if ( iCounter == 1 ) | |
43 | + sUnit = "KiB"; | |
44 | + else if ( iCounter == 2 ) | |
45 | + sUnit = "MiB"; | |
46 | + else if ( iCounter == 3 ) | |
47 | + sUnit = "GiB"; | |
48 | + else if ( iCounter == 4 ) | |
49 | + sUnit = "TiB"; | |
50 | + else | |
51 | + sUnit = "N/A"; | |
52 | + | |
53 | + /* write number */ | |
54 | + return sprintf ( _cDst, "%5.1f %s", dSize, sUnit ); | |
55 | +} | |
56 | +/* END progress mod */ | |
57 | + | |
58 | /* Copy a regular file from SRC_NAME to DST_NAME. | |
59 | If the source file contains holes, copies holes and blocks of zeros | |
60 | in the source file as holes in the destination file. | |
f2e36e57 | 61 | @@ -706,8 +756,146 @@ |
dbfc1835 | 62 | buf_alloc = xmalloc (buf_size + buf_alignment_slop); |
63 | buf = ptr_align (buf_alloc, buf_alignment); | |
64 | ||
dbfc1835 | 65 | + /* BEGIN progress mod */ |
66 | + /* create a field of 6 lines */ | |
f2e36e57 | 67 | + char ** cProgressField = ( char ** ) calloc ( 6, sizeof ( char * ) ); |
dbfc1835 | 68 | + /* get console width */ |
f2e36e57 | 69 | + int iBarLength = 80; |
dbfc1835 | 70 | + struct winsize win; |
71 | + if ( ioctl (STDOUT_FILENO, TIOCGWINSZ, (char *) &win) == 0 && win.ws_col > 0 ) | |
72 | + iBarLength = win.ws_col; | |
73 | + /* create rows */ | |
f2e36e57 | 74 | + int it; |
dbfc1835 | 75 | + for ( it = 0; it < 6; it++ ) |
76 | + { | |
77 | + cProgressField[it] = ( char * ) malloc ( iBarLength + 1 ); | |
78 | + /* init with spaces */ | |
79 | + int j; | |
80 | + for ( j = 0; j < iBarLength; j++ ) | |
81 | + cProgressField[it][j] = ' '; | |
82 | + cProgressField[it][iBarLength] = '\0'; | |
83 | + } | |
f2e36e57 | 84 | + |
dbfc1835 | 85 | + /* global progress bar? */ |
86 | + if ( g_iTotalSize ) | |
87 | + { | |
88 | + /* init global progress bar */ | |
89 | + cProgressField[2][0] = '['; | |
90 | + cProgressField[2][iBarLength - 8] = ']'; | |
91 | + cProgressField[2][iBarLength - 7] = ' '; | |
92 | + cProgressField[2][iBarLength - 1] = '%'; | |
f2e36e57 | 93 | + |
dbfc1835 | 94 | + /* total size */ |
95 | + cProgressField[1][iBarLength - 11] = '/'; | |
96 | + file_size_format ( cProgressField[1] + iBarLength - 9, g_iTotalSize, 1 ); | |
f2e36e57 | 97 | + |
dbfc1835 | 98 | + /* show how many files were written */ |
99 | + int sum_length = sprintf ( cProgressField[1], "%d files copied so far...", g_iFilesCopied ); | |
100 | + cProgressField[1][sum_length] = ' '; | |
101 | + } | |
f2e36e57 | 102 | + |
dbfc1835 | 103 | + /* truncate filename? */ |
104 | + int fn_length; | |
105 | + if ( strlen ( src_name ) > iBarLength - 22 ) | |
106 | + fn_length = | |
107 | + sprintf ( cProgressField[4], "...%s", src_name + ( strlen ( src_name ) - iBarLength + 25 ) ); | |
108 | + else | |
109 | + fn_length = sprintf ( cProgressField[4], "%s", src_name ); | |
110 | + cProgressField[4][fn_length] = ' '; | |
f2e36e57 | 111 | + |
dbfc1835 | 112 | + /* filesize */ |
113 | + cProgressField[4][iBarLength - 11] = '/'; | |
114 | + file_size_format ( cProgressField[4] + iBarLength - 9, src_open_sb.st_size, 0 ); | |
f2e36e57 | 115 | + |
116 | + int iCountDown = 1; | |
dbfc1835 | 117 | + char * sProgressBar = cProgressField[5]; |
118 | + sProgressBar[0] = '['; | |
119 | + sProgressBar[iBarLength - 8] = ']'; | |
120 | + sProgressBar[iBarLength - 7] = ' '; | |
121 | + sProgressBar[iBarLength - 1] = '%'; | |
f2e36e57 | 122 | + |
123 | + /* this will always save the time in between */ | |
124 | + struct timeval last_time; | |
125 | + gettimeofday ( & last_time, NULL ); | |
126 | + int last_size = g_iTotalWritten; | |
dbfc1835 | 127 | + /* END progress mod */ |
f2e36e57 | 128 | + |
dca140ed | 129 | while (true) |
dbfc1835 | 130 | { |
131 | + if (progress) { | |
132 | + /* BEGIN progress mod */ | |
133 | + /* update countdown */ | |
134 | + iCountDown--; | |
135 | + if ( iCountDown < 0 ) | |
136 | + iCountDown = 100; | |
f2e36e57 | 137 | + |
dbfc1835 | 138 | + /* just print one line with the percentage, but not always */ |
139 | + if ( iCountDown == 0 ) | |
140 | + { | |
f2e36e57 | 141 | + /* calculate current speed */ |
142 | + struct timeval cur_time; | |
143 | + gettimeofday ( & cur_time, NULL ); | |
144 | + int cur_size = g_iTotalWritten + n_read_total / 1024; | |
145 | + int usec_elapsed = cur_time.tv_usec - last_time.tv_usec; | |
146 | + double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
147 | + sec_elapsed += ( double ) ( cur_time.tv_sec - last_time.tv_sec ); | |
148 | + int copy_speed = ( int ) ( ( double ) ( cur_size - last_size ) | |
149 | + / sec_elapsed ); | |
150 | + char s_copy_speed[20]; | |
151 | + file_size_format ( s_copy_speed, copy_speed, 1 ); | |
152 | + /* update vars */ | |
153 | + last_time = cur_time; | |
154 | + last_size = cur_size; | |
155 | + | |
156 | + /* how many time has passed since the start? */ | |
157 | + int isec_elapsed = cur_time.tv_sec - g_oStartTime.tv_sec; | |
158 | + int sec_remaining = ( int ) ( ( double ) isec_elapsed / cur_size | |
159 | + * g_iTotalSize ) - isec_elapsed; | |
160 | + int min_remaining = sec_remaining / 60; | |
161 | + sec_remaining -= min_remaining * 60; | |
162 | + int hours_remaining = min_remaining / 60; | |
163 | + min_remaining -= hours_remaining * 60; | |
164 | + /* print out */ | |
165 | + sprintf ( cProgressField[3], | |
166 | + "Copying at %s/s (about %dh %dm %ds remaining)", s_copy_speed, | |
167 | + hours_remaining, min_remaining, sec_remaining ); | |
168 | + | |
dbfc1835 | 169 | + int fs_len; |
170 | + if ( g_iTotalSize ) | |
171 | + { | |
172 | + /* global progress bar */ | |
173 | + file_progress_bar ( cProgressField[2], iBarLength, | |
174 | + g_iTotalWritten + n_read_total / 1024, g_iTotalSize ); | |
f2e36e57 | 175 | + |
dbfc1835 | 176 | + /* print the global status */ |
177 | + fs_len = file_size_format ( cProgressField[1] + iBarLength - 21, | |
178 | + g_iTotalWritten + n_read_total / 1024, 1 ); | |
179 | + cProgressField[1][iBarLength - 21 + fs_len] = ' '; | |
180 | + } | |
f2e36e57 | 181 | + |
dbfc1835 | 182 | + /* current progress bar */ |
183 | + file_progress_bar ( sProgressBar, iBarLength, n_read_total, src_open_sb.st_size ); | |
f2e36e57 | 184 | + |
dbfc1835 | 185 | + /* print the status */ |
186 | + fs_len = file_size_format ( cProgressField[4] + iBarLength - 21, n_read_total, 0 ); | |
187 | + cProgressField[4][iBarLength - 21 + fs_len] = ' '; | |
f2e36e57 | 188 | + |
dbfc1835 | 189 | + /* print the field */ |
190 | + for ( it = g_iTotalSize ? 0 : 3; it < 6; it++ ) | |
191 | + { | |
f2e36e57 | 192 | + printf ( "\033[K%s\n", cProgressField[it] ); |
dbfc1835 | 193 | + if ( strlen ( cProgressField[it] ) < iBarLength ) |
194 | + printf ( "" ); | |
195 | + } | |
196 | + if ( g_iTotalSize ) | |
197 | + printf ( "\r\033[6A" ); | |
198 | + else | |
199 | + printf ( "\r\033[3A" ); | |
200 | + fflush ( stdout ); | |
201 | + } | |
202 | + /* END progress mod */ | |
203 | + } | |
f2e36e57 | 204 | + |
dbfc1835 | 205 | word *wp = NULL; |
206 | ||
207 | ssize_t n_read = read (source_desc, buf, buf_size); | |
f2e36e57 | 208 | @@ -788,6 +976,19 @@ |
dbfc1835 | 209 | /proc with linux kernels from at least 2.6.9 .. 2.6.29. */ |
210 | } | |
211 | } | |
212 | +if (progress) { | |
213 | + /* BEGIN progress mod */ | |
214 | + /* update total size */ | |
215 | + g_iTotalWritten += n_read_total / 1024; | |
216 | + g_iFilesCopied++; | |
f2e36e57 | 217 | + |
dbfc1835 | 218 | + int i; |
219 | + for ( i = 0; i < 6; i++ ) | |
220 | + free ( cProgressField[i] ); | |
221 | + free ( cProgressField ); | |
222 | + /* END progress mod */ | |
223 | +} | |
224 | + | |
225 | ||
226 | /* If the file ends with a `hole', we need to do something to record | |
227 | the length of the file. On modern systems, calling ftruncate does | |
228 | diff -ru coreutils-8.4.orig/src/copy.h coreutils-8.4/src/copy.h | |
229 | --- coreutils-8.4.orig/src/copy.h 2010-01-25 16:03:29.606930239 +0100 | |
f2e36e57 | 230 | +++ coreutils-8.4/src/copy.h 2010-01-26 15:35:30.934163303 +0100 |
dbfc1835 | 231 | @@ -222,6 +222,9 @@ |
232 | Create destination directories as usual. */ | |
233 | bool symbolic_link; | |
234 | ||
235 | + /* if true, draw a nice progress bar on screen */ | |
236 | + bool progress_bar; | |
237 | + | |
238 | /* If true, do not copy a nondirectory that has an existing destination | |
239 | with the same or newer modification time. */ | |
240 | bool update; | |
f2e36e57 | 241 | @@ -280,4 +283,15 @@ |
dbfc1835 | 242 | bool chown_failure_ok (struct cp_options const *); |
243 | mode_t cached_umask (void); | |
244 | ||
245 | +/* BEGIN progress mod */ | |
246 | +int file_size_format ( char * _cDst, int _iSize, int _iCounter ); | |
247 | + | |
248 | +long g_iTotalSize; | |
249 | +long g_iTotalWritten; | |
250 | +int g_iFilesCopied; | |
f2e36e57 | 251 | +struct timeval g_oStartTime; |
252 | +int g_iTotalFiles; | |
dbfc1835 | 253 | +bool progress; |
254 | +/* END progress mod */ | |
255 | + | |
256 | #endif | |
0d2793d8 JB |
257 | --- coreutils-8.9/src/cp.c.orig 2011-01-01 22:19:23.000000000 +0100 |
258 | +++ coreutils-8.9/src/cp.c 2011-01-09 13:07:02.769898177 +0100 | |
259 | @@ -141,6 +141,7 @@ | |
dbfc1835 | 260 | {"target-directory", required_argument, NULL, 't'}, |
261 | {"update", no_argument, NULL, 'u'}, | |
262 | {"verbose", no_argument, NULL, 'v'}, | |
263 | + {"progress-bar", no_argument, NULL, 'g'}, | |
264 | {GETOPT_HELP_OPTION_DECL}, | |
265 | {GETOPT_VERSION_OPTION_DECL}, | |
266 | {NULL, 0, NULL, 0} | |
0d2793d8 JB |
267 | @@ -181,6 +182,7 @@ |
268 | opened, remove it and try again (redundant if\ | |
269 | \n\ | |
dbfc1835 | 270 | the -n option is used)\n\ |
271 | + -g, --progress-bar add progress-bar\n\ | |
0d2793d8 JB |
272 | -i, --interactive prompt before overwrite (overrides a previous -n\ |
273 | \n\ | |
dbfc1835 | 274 | option)\n\ |
0d2793d8 | 275 | @@ -621,6 +623,57 @@ |
dbfc1835 | 276 | quote (file[n_files - 1])); |
277 | } | |
f2e36e57 | 278 | |
dbfc1835 | 279 | + struct timeval start_time; |
f2e36e57 | 280 | +if (progress) { |
dbfc1835 | 281 | + /* BEGIN progress mod */ |
282 | + g_iTotalSize = 0; | |
283 | + g_iFilesCopied = 0; | |
284 | + g_iTotalWritten = 0; | |
f2e36e57 | 285 | + |
dbfc1835 | 286 | + /* save time */ |
287 | + gettimeofday ( & start_time, NULL ); | |
f2e36e57 | 288 | + g_oStartTime = start_time; |
289 | + | |
290 | + printf ( "Calculating total size... \r" ); | |
291 | + fflush ( stdout ); | |
292 | + long iTotalSize = 0; | |
293 | + int iFiles = n_files; | |
294 | + if ( ! target_directory ) | |
295 | + iFiles = n_files - 1; | |
296 | + int j; | |
297 | + for (j = 0; j < iFiles; j++) | |
298 | + { | |
52480cbc | 299 | + /* call du -s for each file */ |
300 | + /* create command */ | |
301 | + char command[1024]; | |
302 | + sprintf ( command, "du -s \"%s\"", file[j] ); | |
303 | + /* TODO: replace all quote signs in file[i] */ | |
304 | + | |
305 | + FILE *fp; | |
306 | + char output[1024]; | |
307 | + | |
308 | + /* run command */ | |
309 | + fp = popen(command, "r"); | |
310 | + if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { | |
311 | + printf("failed to run du.\n" ); | |
312 | + } | |
313 | + else | |
314 | + { | |
315 | + /* isolate size */ | |
316 | + strchr ( output, '\t' )[0] = '\0'; | |
317 | + iTotalSize += atol ( output ); | |
f2e36e57 | 318 | + |
52480cbc | 319 | + printf ( "Calculating total size... %d\r", iTotalSize ); |
f2e36e57 | 320 | + fflush ( stdout ); |
52480cbc | 321 | + } |
f2e36e57 | 322 | + |
52480cbc | 323 | + /* close */ |
324 | + pclose(fp); | |
f2e36e57 | 325 | + } |
326 | + g_iTotalSize = iTotalSize; | |
dbfc1835 | 327 | + /* END progress mod */ |
328 | +} | |
f2e36e57 | 329 | + |
dbfc1835 | 330 | if (target_directory) |
331 | { | |
f2e36e57 | 332 | /* cp file1...filen edir |
0d2793d8 | 333 | @@ -763,6 +816,46 @@ |
dbfc1835 | 334 | ok = copy (source, new_dest, 0, x, &unused, NULL); |
335 | } | |
f2e36e57 | 336 | |
337 | +if (progress) { | |
dbfc1835 | 338 | + /* BEGIN progress mod */ |
339 | + /* remove everything */ | |
340 | + int i; | |
341 | + if ( g_iTotalSize ) | |
342 | + { | |
343 | + for ( i = 0; i < 6; i++ ) | |
344 | + printf ( "\033[K\n" ); | |
345 | + printf ( "\r\033[6A" ); | |
346 | + } | |
347 | + else | |
348 | + { | |
349 | + for ( i = 0; i < 3; i++ ) | |
350 | + printf ( "\033[K\n" ); | |
351 | + printf ( "\r\033[3A" ); | |
352 | + } | |
f2e36e57 | 353 | + |
dbfc1835 | 354 | + /* save time */ |
355 | + struct timeval end_time; | |
356 | + gettimeofday ( & end_time, NULL ); | |
357 | + int usec_elapsed = end_time.tv_usec - start_time.tv_usec; | |
358 | + double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
359 | + sec_elapsed += ( double ) ( end_time.tv_sec - start_time.tv_sec ); | |
f2e36e57 | 360 | + |
dbfc1835 | 361 | + /* get total size */ |
362 | + char sTotalWritten[20]; | |
363 | + file_size_format ( sTotalWritten, g_iTotalSize, 1 ); | |
364 | + /* TODO: using g_iTotalWritten would be more correct, but is less accurate */ | |
f2e36e57 | 365 | + |
dbfc1835 | 366 | + /* calculate speed */ |
367 | + int copy_speed = ( int ) ( ( double ) g_iTotalWritten / sec_elapsed ); | |
368 | + char s_copy_speed[20]; | |
369 | + file_size_format ( s_copy_speed, copy_speed, 1 ); | |
f2e36e57 | 370 | + |
dbfc1835 | 371 | + /* good-bye message */ |
f2e36e57 | 372 | + printf ( "%d files (%s) copied in %.1f seconds (%s/s).\n", g_iFilesCopied, sTotalWritten, |
dbfc1835 | 373 | + sec_elapsed, s_copy_speed ); |
374 | + /* END progress mod */ | |
375 | +} | |
f2e36e57 | 376 | + |
dbfc1835 | 377 | return ok; |
378 | } | |
f2e36e57 | 379 | |
0d2793d8 | 380 | @@ -795,6 +888,7 @@ |
dbfc1835 | 381 | x->recursive = false; |
382 | x->sparse_mode = SPARSE_AUTO; | |
383 | x->symbolic_link = false; | |
384 | + x->progress_bar = false; | |
385 | x->set_mode = false; | |
386 | x->mode = 0; | |
387 | ||
0d2793d8 | 388 | @@ -933,7 +1027,7 @@ |
dbfc1835 | 389 | we'll actually use backup_suffix_string. */ |
390 | backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
391 | ||
392 | - while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:T", | |
393 | + while ((c = getopt_long (argc, argv, "abdfgHilLnprst:uvxPRS:T", | |
394 | long_opts, NULL)) | |
395 | != -1) | |
396 | { | |
0d2793d8 | 397 | @@ -990,6 +1084,10 @@ |
dbfc1835 | 398 | x.unlink_dest_after_failed_open = true; |
399 | break; | |
f2e36e57 | 400 | |
dbfc1835 | 401 | + case 'g': |
402 | + progress = true; | |
403 | + break; | |
f2e36e57 | 404 | + |
dbfc1835 | 405 | case 'H': |
406 | x.dereference = DEREF_COMMAND_LINE_ARGUMENTS; | |
dbfc1835 | 407 | break; |