Hi! I tested it on 32bit & 64bit x86/UltraSPARC/PowerPC machines. Changelog: ==========
copy.c: - Added progress_bar_check(): Source file size check Max console line length check - Fixed progress_bar_print_speed(): New algorythm for determining copying speed size - Progress_bar_print_size() rewritten - Fixed progress_bar_print_eta() cp.c: - Fixed help patch code: --- copy.c 2006-05-12 09:04:29.000000000 +0200 +++ copy.c 2007-12-31 03:04:24.000000000 +0100 @@ -17,6 +17,8 @@ /* Extracted from cp.c and librarified by Jim Meyering. */ +/* Progress bar support add by Andrea Di Pasquale (whyx) email: [EMAIL PROTECTED] */ + #include <config.h> #include <stdio.h> #include <assert.h> @@ -29,6 +31,10 @@ # include <priv.h> #endif +#if HAVE_SYS_IOCTL_H +# include <sys/ioctl.h> +#endif + #include "system.h" #include "backupfile.h" #include "copy.h" @@ -43,6 +49,7 @@ #include "hash.h" #include "hash-pjw.h" #include "quote.h" +#include "quotearg.h" #include "same.h" #include "savedir.h" #include "stat-time.h" @@ -50,6 +57,7 @@ #include "utimens.h" #include "xreadlink.h" #include "yesno.h" +#include "xstrtol.h" #ifndef HAVE_FCHMOD # define HAVE_FCHMOD false @@ -191,6 +199,228 @@ return ok; } +/* This function check: + - src dim tot + - console line lenght + If the progress flag is set */ + +int +progress_bar_check(const char *src_name, size_t dim_tot) +{ + size_t line_length = 0; + + /* Check: + if filesize is very little, exit */ + if (! (dim_tot / 1024)) + { + printf("%s: is very little (1 KB required), " \ + "you can't to use progress bar\n", + src_name); + + return -1; + } + + /* By ls.c code */ + { + char const *p = getenv("COLUMNS"); + + if (p && *p) + { + unsigned long int tmp_ulong; + + if (xstrtoul (p, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK + && 0 < tmp_ulong && tmp_ulong <= SIZE_MAX) + line_length = tmp_ulong; + else + error(0, 0, + _("ignoring invalid width in environment variable COLUMNS: %s"), + quotearg (p)); + } + } + +#ifdef TIOCGWINSZ + { + struct winsize ws; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 + && 0 < ws.ws_col && ws.ws_col == (size_t) ws.ws_col) + line_length = ws.ws_col; + } +#endif + + if (line_length < 125) + { + if (! line_length) + printf("(null): COLUMNS not found, " \ + "you can't to use progress bar\n"); + else + printf("%d: console line lenght is very short, " \ + "you can't to use progress bar\n", line_length); + + return -1; + } + + return 0; +} + +/* This function displays a progress bar + if the progress flag is set. + It uses a 1:2 scales. */ + +void +progress_bar_print(size_t dim_tot, size_t dim_cur) +{ + int i; + size_t per_tot, per_cur, per_tot_scl, per_cur_scl; + + /* Size in KiB */ + dim_tot /= 1024; + dim_cur /= 1024; + + per_tot = 100; + /* total percentage */ + per_cur = (per_tot * dim_cur) / dim_tot; + /* current percentage */ + + /* 1:2 scale */ + per_tot_scl = per_tot / 2; + per_cur_scl = per_cur / 2; + + /* Refresh ther bar indicator */ + printf("\r ["); + + /* Display the bar indicator: + - = : indicates a part the bar + - > : indicates the end of the bar + (if it's finish, convert '>' to '='*/ + for (i = 0; i < per_cur_scl; i++) + if ((i + 1) == per_cur_scl) + if (per_cur_scl == 50) + putchar('='); + else + putchar('>'); + else + putchar('='); + + for (i = per_cur_scl; i < per_tot_scl; i++) + putchar(' '); + + printf("] %3d\% | ", per_cur); + + fflush(stdout); +} + +/* This function displays speed copy + if the progress flag is set. */ + +void +progress_bar_print_speed(struct tm *tm_init, + size_t *speed, size_t *speed_last) +{ + time_t time_cur; + struct tm tm_cur; + size_t speed_si; + float speed_last_, speed_si_; + int type = 0; + + time_cur = time(NULL); + tm_cur = *(struct tm *) localtime(&time_cur); + + if (tm_init->tm_sec == tm_cur.tm_sec) + { + if (tm_init->tm_sec == 60) + tm_init->tm_sec = 0; + else + tm_init->tm_sec += 1; + + *speed_last = *speed; + *speed = 0; + } + else if (tm_init->tm_sec != tm_cur.tm_sec + 1) + /* If the disk crashes, again */ + tm_init->tm_sec = tm_cur.tm_sec + 1; + + if (*speed_last == 0) + *speed_last = *speed; + + /* Convert to max type */ + for (speed_si = 1024; *speed_last / speed_si; speed_si *= 1024) + type++; + + speed_si_ = (float) (speed_si / 1024); + speed_last_ = ((float) *speed_last) / speed_si_; + + printf("%12.02f %s | ", speed_last_, + type == 1 ? "KiB/s" : type == 2 ? "MiB/s" : + type == 3 ? "GiB/s" : type == 4 ? "TiB/s" : + type == 5 ? "PiB/s" : type == 6 ? "EiB/s" : + type == 7 ? "ZiB/s" : "YiB/s"); + + fflush(stdout); +} + +/* This function displays source/dest size files + if the progress flag is set. */ + +void +progress_bar_print_size(size_t dim_tot, size_t dim_cur) +{ + size_t dim_si; + float dim_tot_, dim_cur_, dim_si_; + int type = 0; + + /* Convert to max type */ + for (dim_si = 1024; dim_tot / dim_si; dim_si *= 1024) + type++; + + dim_si_ = (float) (dim_si / 1024); + dim_tot_ = ((float) dim_tot) / dim_si_; + dim_cur_ = ((float) dim_cur) / dim_si_; + + printf("%10.02f/%.02f %s | ", dim_cur_, dim_tot_, + type == 1 ? "KiB" : type == 2 ? "MiB" : + type == 3 ? "GiB" : type == 4 ? "TiB" : + type == 5 ? "PiB" : type == 6 ? "EiB" : + type == 7 ? "ZiB" : "YiB"); + + fflush(stdout); +} + +/* This function displays ETA copy + if the progress flag is set. */ + +void +progress_bar_print_eta(size_t dim_tot, size_t dim_cur, + size_t speed_last) +{ + size_t dim_diff = 0, + eta = 0; + int sec, min, hour; + + /* Convert in KiB */ + dim_tot /= 1024; + dim_cur /= 1024; + + dim_diff = dim_tot - dim_cur; + speed_last /= 1024; + + /* speed_last : 1 sec = dim_diff : eta + + eta = 1 * dim_diff + ------------ + speed_last */ + + eta = dim_diff / speed_last; + + min = eta / 60; + sec = eta - (min * 60); + hour = min / 60; + + printf("ETA: %02d:%02d:%02d ", hour, min, sec); + + fflush(stdout); +} + /* Copy a regular file from SRC_NAME to DST_NAME. If the source file contains holes, copies holes and blocks of zeros in the source file as holes in the destination file. @@ -222,6 +452,15 @@ off_t n_read_total = 0; bool last_write_made_hole = false; bool make_holes = false; + /* Progress bar */ + int pb_check; + size_t dim_tot = 0, + dim_cur = 0; + /* speed time */ + time_t time_init; + struct tm tm_init; + size_t speed = 0, + speed_last = 0; source_desc = open (src_name, O_RDONLY | O_BINARY); if (source_desc < 0) @@ -326,6 +565,18 @@ buf = alloca (buf_size + sizeof (int) + buf_alignment - 1); buf = ptr_align (buf, buf_alignment); + if (x->progress) + { + dim_tot = src_sb->st_size; + + if (! (pb_check = progress_bar_check(src_name, dim_tot))) + { + time_init = time(NULL); + tm_init = *(struct tm *) localtime(&time_init); + tm_init.tm_sec += 1; + } + } + for (;;) { ssize_t n_read = read (source_desc, buf, buf_size); @@ -388,10 +639,34 @@ return_val = false; goto close_src_and_dst_desc; } + + /* if the progress flag is set, it uses a progress bar */ + if (x->progress && ! pb_check) + { + dim_cur += n; + + /* print progress bar */ + progress_bar_print(dim_tot, dim_cur); + + speed += n; + + /* print progress bar speed */ + progress_bar_print_speed(&tm_init, &speed, &speed_last); + + /* print progress bar size */ + progress_bar_print_size(dim_tot, dim_cur); + + /* print progress bar ETA */ + progress_bar_print_eta(dim_tot, dim_cur, speed_last); + } + last_write_made_hole = false; } } + if (x->progress && ! pb_check) + putchar('\n'); + /* If the file ends with a `hole', something needs to be written at the end. Otherwise the kernel would truncate the file at the end of the last write operation. */ --- copy.h 2005-07-03 11:31:19.000000000 +0200 +++ copy.h 2007-12-21 02:31:22.000000000 +0100 @@ -83,6 +83,9 @@ { enum backup_type backup_type; + /* If true, Display a progress bar */ + bool progress; + /* If true, copy all files except (directories and, if not dereferencing them, symbolic links,) as if they were regular files. */ bool copy_as_regular; --- cp.c 2005-09-16 09:50:33.000000000 +0200 +++ cp.c 2007-12-30 23:48:48.000000000 +0100 @@ -117,6 +117,7 @@ { {"archive", no_argument, NULL, 'a'}, {"backup", optional_argument, NULL, 'b'}, + {"progress", no_argument, NULL, 'B'}, {"copy-contents", no_argument, NULL, COPY_CONTENTS_OPTION}, {"dereference", no_argument, NULL, 'L'}, {"force", no_argument, NULL, 'f'}, @@ -170,6 +171,8 @@ -a, --archive same as -dpR\n\ --backup[=CONTROL] make a backup of each existing destination file\n\ -b like --backup but does not accept an argument\n\ + -B --progress show a progress bar\n\ + (filesize > 1 KB / console line lenght >= 125)\n\ --copy-contents copy contents of special files when recursive\n\ -d same as --no-dereference --preserve=link \n\ "), stdout); @@ -672,6 +675,7 @@ static void cp_option_init (struct cp_options *x) { + x->progress = false; x->copy_as_regular = true; x->dereference = DEREF_UNDEFINED; x->unlink_dest_before_opening = false; @@ -811,7 +815,7 @@ we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); - while ((c = getopt_long (argc, argv, "abdfHilLprst:uvxPRS:T", + while ((c = getopt_long (argc, argv, "abBdfHilLprst:uvxPRS:T", long_opts, NULL)) != -1) { @@ -838,6 +842,10 @@ version_control_string = optarg; break; + case 'B': + x.progress = true; + break; + case COPY_CONTENTS_OPTION: copy_contents = true; break; Thank You Andrea
cp-progress_bar-coreutils-5.97.tar.gz
Description: application/compressed-tar
cp-progress_bar-coreutils-6.9.tar.gz
Description: application/compressed-tar