[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: cp progress bar
From: |
Andrea Di Pasquale |
Subject: |
Re: cp progress bar |
Date: |
Mon, 31 Dec 2007 04:27:35 +0100 |
Mike write:
you didnt say whether your host was a 32bit or 64bit system
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 (coreutils 5.97):
--- 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:
address@hidden */
+
#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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: cp progress bar,
Andrea Di Pasquale <=