Lines 17-22
Link Here
|
17 |
|
17 |
|
18 |
/* Extracted from cp.c and librarified by Jim Meyering. */ |
18 |
/* Extracted from cp.c and librarified by Jim Meyering. */ |
19 |
|
19 |
|
|
|
20 |
/* Progress bar support added by Miika Pekkarinen. miipekk@ihme.org */ |
21 |
|
20 |
#include <config.h> |
22 |
#include <config.h> |
21 |
#include <stdio.h> |
23 |
#include <stdio.h> |
22 |
#include <assert.h> |
24 |
#include <assert.h> |
Lines 26-31
Link Here
|
26 |
# include <hurd.h> |
28 |
# include <hurd.h> |
27 |
#endif |
29 |
#endif |
28 |
|
30 |
|
|
|
31 |
#ifdef GWINSZ_IN_SYS_IOCTL |
32 |
# include <sys/ioctl.h> |
33 |
#endif |
34 |
|
29 |
#include "system.h" |
35 |
#include "system.h" |
30 |
#include "error.h" |
36 |
#include "error.h" |
31 |
#include "backupfile.h" |
37 |
#include "backupfile.h" |
Lines 42-47
Link Here
|
42 |
#include "same.h" |
48 |
#include "same.h" |
43 |
#include "utimens.h" |
49 |
#include "utimens.h" |
44 |
#include "xreadlink.h" |
50 |
#include "xreadlink.h" |
|
|
51 |
#include "xstrtol.h" |
45 |
#include "acl.h" |
52 |
#include "acl.h" |
46 |
|
53 |
|
47 |
#ifdef USE_XATTR |
54 |
#ifdef USE_XATTR |
Lines 77-82
struct F_triple
Link Here
|
77 |
/* Initial size of the above hash table. */ |
84 |
/* Initial size of the above hash table. */ |
78 |
#define DEST_INFO_INITIAL_CAPACITY 61 |
85 |
#define DEST_INFO_INITIAL_CAPACITY 61 |
79 |
|
86 |
|
|
|
87 |
/* How many samples to take while calculating average speed */ |
88 |
#define SAMPLE_MAX 10 |
89 |
|
80 |
int euidaccess (); |
90 |
int euidaccess (); |
81 |
int yesno (); |
91 |
int yesno (); |
82 |
|
92 |
|
Lines 189-194
copy_dir (const char *src_path_in, const
Link Here
|
189 |
return -ret; |
199 |
return -ret; |
190 |
} |
200 |
} |
191 |
|
201 |
|
|
|
202 |
/* Shorten a string '/long path/long file' to 'long fi...' |
203 |
Also adds padding bytes to end of the string if necessary */ |
204 |
char *shorten_path(const char *str, int max_width) |
205 |
{ |
206 |
char *shortname; |
207 |
char *filename = (char *) (rindex(str, '/')); |
208 |
int len; |
209 |
|
210 |
if (filename == NULL) |
211 |
{ |
212 |
filename = (char *) str; |
213 |
} |
214 |
else |
215 |
{ |
216 |
filename = (char *) &filename[1]; |
217 |
} |
218 |
|
219 |
len = strlen(filename); |
220 |
shortname = (char *) xmalloc (max_width + 1); |
221 |
strncpy (shortname, filename, max_width); |
222 |
shortname[max_width] = '\0'; |
223 |
if (len > max_width) |
224 |
{ |
225 |
memset(&shortname[max_width - 3], '.', 3); |
226 |
} |
227 |
else |
228 |
{ |
229 |
memset(&shortname[len], ' ', max_width - len); |
230 |
} |
231 |
|
232 |
return shortname; |
233 |
} |
234 |
|
235 |
char *si_units(off_t size) |
236 |
{ |
237 |
const static int buf_size = 20; |
238 |
char *buf; |
239 |
static char *unit_array[] = { "B", "KiB", "MiB", "GiB", "" }; |
240 |
int i; |
241 |
|
242 |
buf = xmalloc(20); |
243 |
for (i = 0; size > 10000; i++) |
244 |
{ |
245 |
if (unit_array[i][0] == '\0') |
246 |
{ |
247 |
i--; |
248 |
break; |
249 |
} |
250 |
size /= 1024; |
251 |
} |
252 |
|
253 |
snprintf (buf, buf_size, "%lu %s", (unsigned long)size, unit_array[i]); |
254 |
|
255 |
return buf; |
256 |
} |
257 |
|
192 |
/* Copy a regular file from SRC_PATH to DST_PATH. |
258 |
/* Copy a regular file from SRC_PATH to DST_PATH. |
193 |
If the source file contains holes, copies holes and blocks of zeros |
259 |
If the source file contains holes, copies holes and blocks of zeros |
194 |
in the source file as holes in the destination file. |
260 |
in the source file as holes in the destination file. |
Lines 216-221
copy_reg (const char *src_path, const ch
Link Here
|
216 |
off_t n_read_total = 0; |
282 |
off_t n_read_total = 0; |
217 |
int last_write_made_hole = 0; |
283 |
int last_write_made_hole = 0; |
218 |
int make_holes = (x->sparse_mode == SPARSE_ALWAYS); |
284 |
int make_holes = (x->sparse_mode == SPARSE_ALWAYS); |
|
|
285 |
time_t t_start; |
286 |
time_t t_last; |
287 |
time_t t_now; |
288 |
int last_bytes = 0; |
289 |
int progress_bar_printed = 0; |
290 |
char *shortname = NULL; |
291 |
off_t sample_window[SAMPLE_MAX]; |
292 |
off_t sample_sum = 0; |
293 |
int sample_count = 0; |
294 |
int line_length = 80; |
295 |
#ifdef TIOCGWINSZ |
296 |
struct winsize ws; |
297 |
#endif |
219 |
|
298 |
|
220 |
source_desc = open (src_path, O_RDONLY); |
299 |
source_desc = open (src_path, O_RDONLY); |
221 |
if (source_desc < 0) |
300 |
if (source_desc < 0) |
Lines 313-318
copy_reg (const char *src_path, const ch
Link Here
|
313 |
|
389 |
|
314 |
buf = (char *) alloca (buf_size + sizeof (int)); |
390 |
buf = (char *) alloca (buf_size + sizeof (int)); |
315 |
|
391 |
|
|
|
392 |
time (&t_start); |
393 |
t_last = t_start; |
394 |
|
316 |
for (;;) |
395 |
for (;;) |
317 |
{ |
396 |
{ |
318 |
ssize_t n_read = read (source_desc, buf, buf_size); |
397 |
ssize_t n_read = read (source_desc, buf, buf_size); |
Lines 377-382
copy_reg (const char *src_path, const ch
Link Here
|
377 |
} |
456 |
} |
378 |
last_write_made_hole = 0; |
457 |
last_write_made_hole = 0; |
379 |
} |
458 |
} |
|
|
459 |
|
460 |
time (&t_now); |
461 |
|
462 |
/* Progress bar stuff */ |
463 |
if (! x->pbar_show || t_now - t_start < x->pbar_delay) |
464 |
{ |
465 |
continue; |
466 |
} |
467 |
|
468 |
if (! progress_bar_printed) |
469 |
{ |
470 |
/* Column width check code copied from ls.c */ |
471 |
char const *p = getenv ("COLUMNS"); |
472 |
if (p && *p) |
473 |
{ |
474 |
long int tmp_long; |
475 |
if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK |
476 |
&& 0 < tmp_long && tmp_long <= INT_MAX) |
477 |
{ |
478 |
line_length = (int) tmp_long; |
479 |
} |
480 |
else |
481 |
{ |
482 |
error (0, 0, |
483 |
_("ignoring invalid width in environment \ |
484 |
variable COLUMNS: %s"), |
485 |
quotearg (p)); |
486 |
} |
487 |
} |
488 |
|
489 |
#ifdef TIOCGWINSZ |
490 |
if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0) |
491 |
{ |
492 |
line_length = ws.ws_col; |
493 |
} |
494 |
#endif |
495 |
if (line_length < 50) |
496 |
{ |
497 |
continue; |
498 |
} |
499 |
|
500 |
/* Take a short filename for progress bar */ |
501 |
shortname = shorten_path(src_path, line_length - 48); |
502 |
progress_bar_printed = 1; |
503 |
} |
504 |
|
505 |
if (t_now == t_last) |
506 |
{ |
507 |
continue; |
508 |
} |
509 |
|
510 |
if (sample_count == SAMPLE_MAX) |
511 |
{ |
512 |
int i; |
513 |
|
514 |
sample_sum -= sample_window[0]; |
515 |
for (i = 0; i < SAMPLE_MAX - 1; i++) |
516 |
{ |
517 |
sample_window[i] = sample_window[i + 1]; |
518 |
} |
519 |
} |
520 |
else |
521 |
{ |
522 |
sample_count++; |
523 |
} |
524 |
|
525 |
{ |
526 |
char *str_size; |
527 |
char *str_speed; |
528 |
char etabuf[64]; |
529 |
time_t t_temp; |
530 |
|
531 |
sample_window[sample_count - 1] = (n_read_total - last_bytes) / |
532 |
(t_now - t_last); |
533 |
sample_sum += sample_window[sample_count - 1]; |
534 |
|
535 |
/* Calculate the remaining time */ |
536 |
t_temp = (src_open_sb.st_size - n_read_total) / (sample_sum / sample_count); |
537 |
|
538 |
/* Don't print the progress bar if the estimated remaining |
539 |
time is low. */ |
540 |
if (progress_bar_printed == 1 && t_temp < x->pbar_min_est) |
541 |
{ |
542 |
continue; |
543 |
} |
544 |
progress_bar_printed = 2; |
545 |
|
546 |
str_size = si_units(src_open_sb.st_size); |
547 |
str_speed = si_units(sample_sum / sample_count); |
548 |
|
549 |
strftime(etabuf, sizeof etabuf, "%H:%M.%S", |
550 |
gmtime(&t_temp)); |
551 |
printf (_("%s | %3d%% | %9s | %9s/s | ETA %s\r"), shortname, |
552 |
(int)(n_read_total * 100 / src_open_sb.st_size), |
553 |
str_size, str_speed, etabuf); |
554 |
fflush (stdout); |
555 |
free(str_size); |
556 |
free(str_speed); |
557 |
t_last = t_now; |
558 |
last_bytes = n_read_total; |
559 |
} |
560 |
} |
561 |
|
562 |
/* Print a newline if progress bar is enabled and has been shown */ |
563 |
if (progress_bar_printed == 2) |
564 |
{ |
565 |
printf ("%s | 100%%\n", shortname); |
380 |
} |
566 |
} |
381 |
|
567 |
|
382 |
/* If the file ends with a `hole', something needs to be written at |
568 |
/* If the file ends with a `hole', something needs to be written at |
Lines 411-416
close_src_desc:
Link Here
|
411 |
{ |
599 |
{ |
412 |
error (0, errno, _("closing %s"), quote (src_path)); |
600 |
error (0, errno, _("closing %s"), quote (src_path)); |
413 |
return_val = -1; |
601 |
return_val = -1; |
|
|
602 |
} |
603 |
|
604 |
if (shortname != NULL) |
605 |
{ |
606 |
free (shortname); |
414 |
} |
607 |
} |
415 |
|
608 |
|
416 |
return return_val; |
609 |
return return_val; |