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
3 +++ coreutils-8.4/src/copy.c 2010-01-26 12:35:40.565408965 +0100
5 return lchmod (name, mode);
8 +/* BEGIN progress mod */
9 +static void file_progress_bar ( char * _cDest, int _iBarLength, int _iProgress, int _iTotal )
11 + // write number to progress bar
12 + float fPercent = ( float ) _iProgress / ( float ) _iTotal * 100.f;
13 + sprintf ( _cDest + ( _iBarLength - 6 ), "%4.1f", fPercent );
15 + _cDest[_iBarLength - 2] = ' ';
17 + // fill rest with '-'
19 + for ( i = 1; i <= _iBarLength - 9; i++ )
21 + if ( fPercent > ( float ) ( i - 1 ) / ( _iBarLength - 10 ) * 100.f )
28 +int file_size_format ( char * _cDst, int _iSize, int _iCounter )
30 + int iCounter = _iCounter;
31 + double dSize = ( double ) _iSize;
32 + while ( dSize >= 1000. )
40 + if ( iCounter == 0 )
42 + else if ( iCounter == 1 )
44 + else if ( iCounter == 2 )
46 + else if ( iCounter == 3 )
48 + else if ( iCounter == 4 )
54 + return sprintf ( _cDst, "%5.1f %s", dSize, sUnit );
56 +/* END progress mod */
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.
63 goto close_src_and_dst_desc;
69 bool clone_ok = clone_file (dest_desc, source_desc) == 0;
71 buf_alloc = xmalloc (buf_size + buf_alignment_slop);
72 buf = ptr_align (buf_alloc, buf_alignment);
75 + char ** cProgressField = ( char ** ) calloc ( 6, sizeof ( char * ) );
76 + int iBarLength = 80;
77 + /* BEGIN progress mod */
78 + /* create a field of 6 lines */
79 + /* get console width */
81 + if ( ioctl (STDOUT_FILENO, TIOCGWINSZ, (char *) &win) == 0 && win.ws_col > 0 )
82 + iBarLength = win.ws_col;
84 + for ( it = 0; it < 6; it++ )
86 + cProgressField[it] = ( char * ) malloc ( iBarLength + 1 );
87 + /* init with spaces */
89 + for ( j = 0; j < iBarLength; j++ )
90 + cProgressField[it][j] = ' ';
91 + cProgressField[it][iBarLength] = '\0';
94 + /* global progress bar? */
97 + /* init global progress bar */
98 + cProgressField[2][0] = '[';
99 + cProgressField[2][iBarLength - 8] = ']';
100 + cProgressField[2][iBarLength - 7] = ' ';
101 + cProgressField[2][iBarLength - 1] = '%';
104 + cProgressField[1][iBarLength - 11] = '/';
105 + file_size_format ( cProgressField[1] + iBarLength - 9, g_iTotalSize, 1 );
107 + /* show how many files were written */
108 + int sum_length = sprintf ( cProgressField[1], "%d files copied so far...", g_iFilesCopied );
109 + cProgressField[1][sum_length] = ' ';
112 + /* truncate filename? */
114 + if ( strlen ( src_name ) > iBarLength - 22 )
116 + sprintf ( cProgressField[4], "...%s", src_name + ( strlen ( src_name ) - iBarLength + 25 ) );
118 + fn_length = sprintf ( cProgressField[4], "%s", src_name );
119 + cProgressField[4][fn_length] = ' ';
122 + cProgressField[4][iBarLength - 11] = '/';
123 + file_size_format ( cProgressField[4] + iBarLength - 9, src_open_sb.st_size, 0 );
124 + char * sProgressBar = cProgressField[5];
125 + sProgressBar[0] = '[';
126 + sProgressBar[iBarLength - 8] = ']';
127 + sProgressBar[iBarLength - 7] = ' ';
128 + sProgressBar[iBarLength - 1] = '%';
129 + /* END progress mod */
130 + int iCountDown = 1;
135 + /* BEGIN progress mod */
136 + /* update countdown */
138 + if ( iCountDown < 0 )
141 + /* just print one line with the percentage, but not always */
142 + if ( iCountDown == 0 )
145 + if ( g_iTotalSize )
147 + /* global progress bar */
148 + file_progress_bar ( cProgressField[2], iBarLength,
149 + g_iTotalWritten + n_read_total / 1024, g_iTotalSize );
151 + /* print the global status */
152 + fs_len = file_size_format ( cProgressField[1] + iBarLength - 21,
153 + g_iTotalWritten + n_read_total / 1024, 1 );
154 + cProgressField[1][iBarLength - 21 + fs_len] = ' ';
157 + /* current progress bar */
158 + file_progress_bar ( sProgressBar, iBarLength, n_read_total, src_open_sb.st_size );
160 + /* print the status */
161 + fs_len = file_size_format ( cProgressField[4] + iBarLength - 21, n_read_total, 0 );
162 + cProgressField[4][iBarLength - 21 + fs_len] = ' ';
164 + /* print the field */
165 + for ( it = g_iTotalSize ? 0 : 3; it < 6; it++ )
167 + printf ( "%s\n", cProgressField[it] );
168 + if ( strlen ( cProgressField[it] ) < iBarLength )
171 + if ( g_iTotalSize )
172 + printf ( "\r\033[6A" );
174 + printf ( "\r\033[3A" );
177 + /* END progress mod */
182 ssize_t n_read = read (source_desc, buf, buf_size);
184 /proc with linux kernels from at least 2.6.9 .. 2.6.29. */
188 + /* BEGIN progress mod */
189 + /* update total size */
190 + g_iTotalWritten += n_read_total / 1024;
194 + for ( i = 0; i < 6; i++ )
195 + free ( cProgressField[i] );
196 + free ( cProgressField );
197 + /* END progress mod */
201 /* If the file ends with a `hole', we need to do something to record
202 the length of the file. On modern systems, calling ftruncate does
203 diff -ru coreutils-8.4.orig/src/copy.h coreutils-8.4/src/copy.h
204 --- coreutils-8.4.orig/src/copy.h 2010-01-25 16:03:29.606930239 +0100
205 +++ coreutils-8.4/src/copy.h 2010-01-25 16:57:54.755683087 +0100
207 Create destination directories as usual. */
210 + /* if true, draw a nice progress bar on screen */
213 /* If true, do not copy a nondirectory that has an existing destination
214 with the same or newer modification time. */
217 bool chown_failure_ok (struct cp_options const *);
218 mode_t cached_umask (void);
220 +/* BEGIN progress mod */
221 +int file_size_format ( char * _cDst, int _iSize, int _iCounter );
224 +long g_iTotalWritten;
227 +/* END progress mod */
230 diff -ru coreutils-8.4.orig/src/cp.c coreutils-8.4/src/cp.c
231 --- coreutils-8.4.orig/src/cp.c 2010-01-25 16:03:29.596930015 +0100
232 +++ coreutils-8.4/src/cp.c 2010-01-26 11:30:10.014160692 +0100
234 {"target-directory", required_argument, NULL, 't'},
235 {"update", no_argument, NULL, 'u'},
236 {"verbose", no_argument, NULL, 'v'},
237 + {"progress-bar", no_argument, NULL, 'g'},
238 {GETOPT_HELP_OPTION_DECL},
239 {GETOPT_VERSION_OPTION_DECL},
242 -f, --force if an existing destination file cannot be\n\
243 opened, remove it and try again (redundant if\n\
244 the -n option is used)\n\
245 + -g, --progress-bar add progress-bar\n\
246 -i, --interactive prompt before overwrite (overrides a previous -n\n\
248 -H follow command-line symbolic links in SOURCE\n\
250 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
251 quote (file[n_files - 1]));
254 + struct timeval start_time;
256 + /* BEGIN progress mod */
258 + g_iFilesCopied = 0;
259 + g_iTotalWritten = 0;
262 + gettimeofday ( & start_time, NULL );
263 + /* END progress mod */
266 if (target_directory)
274 + /* BEGIN progress mod */
275 + printf ( "Calculating total size... \r" );
277 + long iTotalSize = 0;
278 + for (i = 0; i < n_files; i++)
280 + /* call du -s for each file */
281 + /* create command */
282 + char command[1024];
283 + sprintf ( command, "/usr/bin/du -s \"%s\"", file[i] );
284 + /* TODO: replace all quote signs in file[i] */
290 + fp = popen(command, "r");
291 + if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) {
292 + printf("failed to run du.\n" );
297 + strchr ( output, '\t' )[0] = '\0';
298 + iTotalSize += atol ( output );
300 + printf ( "Calculating total size... %d\r", iTotalSize );
307 + g_iTotalSize = iTotalSize;
308 + g_iTotalWritten = 0;
309 + g_iFilesCopied = 0;
310 + /* END progress mod */
313 for (i = 0; i < n_files; i++)
317 ok = copy (source, new_dest, 0, x, &unused, NULL);
321 + /* BEGIN progress mod */
322 + /* remove everything */
324 + if ( g_iTotalSize )
326 + for ( i = 0; i < 6; i++ )
327 + printf ( "\033[K\n" );
328 + printf ( "\r\033[6A" );
332 + for ( i = 0; i < 3; i++ )
333 + printf ( "\033[K\n" );
334 + printf ( "\r\033[3A" );
338 + struct timeval end_time;
339 + gettimeofday ( & end_time, NULL );
340 + int usec_elapsed = end_time.tv_usec - start_time.tv_usec;
341 + double sec_elapsed = ( double ) usec_elapsed / 1000000.f;
342 + sec_elapsed += ( double ) ( end_time.tv_sec - start_time.tv_sec );
344 + /* get total size */
345 + char sTotalWritten[20];
346 + file_size_format ( sTotalWritten, g_iTotalSize, 1 );
347 + /* TODO: using g_iTotalWritten would be more correct, but is less accurate */
349 + /* calculate speed */
350 + int copy_speed = ( int ) ( ( double ) g_iTotalWritten / sec_elapsed );
351 + char s_copy_speed[20];
352 + file_size_format ( s_copy_speed, copy_speed, 1 );
354 + /* good-bye message */
355 + printf ( "%d files (%s) copied in %.1f seconds (%s/s).\n", g_iFilesCopied, sTotalWritten,
356 + sec_elapsed, s_copy_speed );
357 + /* END progress mod */
363 x->recursive = false;
364 x->sparse_mode = SPARSE_AUTO;
365 x->symbolic_link = false;
366 + x->progress_bar = false;
371 we'll actually use backup_suffix_string. */
372 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
374 - while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:T",
375 + while ((c = getopt_long (argc, argv, "abdfgHilLnprst:uvxPRS:T",
379 @@ -974,6 +1069,10 @@
381 x.unlink_dest_after_failed_open = true;
389 x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
390 @@ -1043,6 +1142,7 @@
391 x.symbolic_link = true;
396 if (target_directory)
397 error (EXIT_FAILURE, 0,