Magellan Linux

Contents of /trunk/coreutils/patches-5.94/coreutils-5.94-gen-progress-bar.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 115 - (show annotations) (download)
Sun Mar 18 15:57:37 2007 UTC (17 years, 1 month ago) by niro
File size: 12890 byte(s)
patches for 5.94

1 Upstream has been contacted about this a few times ...
2
3 they dont want progress bars in mv/cp:
4 http://lists.gnu.org/archive/html/bug-coreutils/2003-08/msg00114.html
5 http://lists.gnu.org/archive/html/bug-coreutils/2003-09/msg00083.html
6 http://lists.gnu.org/archive/html/bug-coreutils/2003-09/msg00084.html
7
8 but they don't seem to mind a general util ... add this to future patchset:
9 http://lists.gnu.org/archive/html/bug-coreutils/2003-09/msg00101.html
10 http://lists.gnu.org/archive/html/bug-coreutils/2004-02/msg00071.html
11
12 --- coreutils/src/copy.c
13 +++ coreutils/src/copy.c
14 @@ -17,6 +17,8 @@
15
16 /* Extracted from cp.c and librarified by Jim Meyering. */
17
18 +/* Progress bar support added by Miika Pekkarinen. miipekk@ihme.org */
19 +
20 #include <config.h>
21 #include <stdio.h>
22 #include <assert.h>
23 @@ -29,6 +31,10 @@
24 # include <priv.h>
25 #endif
26
27 +#ifdef GWINSZ_IN_SYS_IOCTL
28 +# include <sys/ioctl.h>
29 +#endif
30 +
31 #include "system.h"
32 #include "backupfile.h"
33 #include "copy.h"
34 @@ -50,6 +56,7 @@
35 #include "utimens.h"
36 #include "xreadlink.h"
37 #include "yesno.h"
38 +#include "xstrtol.h"
39
40 #ifndef HAVE_FCHMOD
41 # define HAVE_FCHMOD false
42 @@ -85,6 +92,8 @@ struct F_triple
43 /* Initial size of the above hash table. */
44 #define DEST_INFO_INITIAL_CAPACITY 61
45
46 +#define SAMPLE_MAX 10
47 +
48 static bool copy_internal (char const *src_name, char const *dst_name,
49 bool new_dst, dev_t device,
50 struct dir_list *ancestors,
51 @@ -191,6 +200,62 @@ copy_dir (char const *src_name_in, char
52 return ok;
53 }
54
55 +/* Shorten a string '/long path/long file' to 'long fi...'
56 + Also adds padding bytes to end of the string if necessary */
57 +char *shorten_name(const char *str, size_t max_width)
58 +{
59 + char *shortname;
60 + char *filename = (char *) (rindex(str, '/'));
61 + size_t len;
62 +
63 + if (filename == NULL)
64 + {
65 + filename = (char *) str;
66 + }
67 + else
68 + {
69 + filename = (char *) &filename[1];
70 + }
71 +
72 + len = strlen(filename);
73 + shortname = (char *) xmalloc (max_width + 1);
74 + strncpy (shortname, filename, max_width);
75 + shortname[max_width] = '\0';
76 + if (len > max_width)
77 + {
78 + memset(&shortname[max_width - 3], '.', 3);
79 + }
80 + else
81 + {
82 + memset(&shortname[len], ' ', max_width - len);
83 + }
84 +
85 + return shortname;
86 +}
87 +
88 +char *si_units(off_t size)
89 +{
90 + const static int buf_size = 20;
91 + char *buf;
92 + static char *unit_array[] = { "B", "KiB", "MiB", "GiB", "" };
93 + size_t i;
94 +
95 + buf = xmalloc(20);
96 + for (i = 0; size > 10000; i++)
97 + {
98 + if (unit_array[i][0] == '\0')
99 + {
100 + i--;
101 + break;
102 + }
103 + size /= 1024;
104 + }
105 +
106 + snprintf (buf, buf_size, "%lu %s", (unsigned long)size, unit_array[i]);
107 +
108 + return buf;
109 +}
110 +
111 /* Copy a regular file from SRC_NAME to DST_NAME.
112 If the source file contains holes, copies holes and blocks of zeros
113 in the source file as holes in the destination file.
114 @@ -222,6 +287,19 @@ copy_reg (char const *src_name, char con
115 off_t n_read_total = 0;
116 bool last_write_made_hole = false;
117 bool make_holes = false;
118 + time_t t_start;
119 + time_t t_last;
120 + time_t t_now;
121 + off_t last_bytes = 0;
122 + int progress_bar_printed = 0;
123 + char *shortname = NULL;
124 + off_t sample_window[SAMPLE_MAX];
125 + off_t sample_sum = 0;
126 + int sample_count = 0;
127 + long int line_length = 0;
128 +#ifdef TIOCGWINSZ
129 + struct winsize ws;
130 +#endif
131
132 source_desc = open (src_name, O_RDONLY | O_BINARY);
133 if (source_desc < 0)
134 @@ -326,6 +404,9 @@ copy_reg (char const *src_name, char con
135 buf = alloca (buf_size + sizeof (int) + buf_alignment - 1);
136 buf = ptr_align (buf, buf_alignment);
137
138 + time (&t_start);
139 + t_last = t_start;
140 +
141 for (;;)
142 {
143 ssize_t n_read = read (source_desc, buf, buf_size);
144 @@ -390,6 +471,113 @@ copy_reg (char const *src_name, char con
145 }
146 last_write_made_hole = false;
147 }
148 +
149 + time (&t_now);
150 +
151 + /* Progress bar stuff */
152 + if (! x->pbar_show || t_now - t_start < x->pbar_delay)
153 + {
154 + continue;
155 + }
156 +
157 + if (! progress_bar_printed)
158 + {
159 + /* Column width check code copied from ls.c */
160 + char const *p = getenv ("COLUMNS");
161 + if (p && *p)
162 + {
163 + long int tmp_long;
164 + if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
165 + && 0 < tmp_long && tmp_long <= INT_MAX)
166 + {
167 + line_length = tmp_long;
168 + }
169 + else
170 + {
171 + error (0, 0,
172 + _("ignoring invalid width in environment \
173 + variable COLUMNS: %s"),
174 + quotearg (p));
175 + }
176 + }
177 +
178 +#ifdef TIOCGWINSZ
179 + if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
180 + {
181 + line_length = ws.ws_col;
182 + }
183 +#endif
184 + if (line_length < 50)
185 + {
186 + continue;
187 + }
188 +
189 + /* Take a short filename for progress bar */
190 + shortname = shorten_name(src_name, line_length - 48);
191 + progress_bar_printed = 1;
192 + }
193 +
194 + if (t_now == t_last)
195 + {
196 + continue;
197 + }
198 +
199 + if (sample_count == SAMPLE_MAX)
200 + {
201 + int i;
202 +
203 + sample_sum -= sample_window[0];
204 + for (i = 0; i < SAMPLE_MAX - 1; i++)
205 + {
206 + sample_window[i] = sample_window[i + 1];
207 + }
208 + }
209 + else
210 + {
211 + sample_count++;
212 + }
213 +
214 + {
215 + char *str_size;
216 + char *str_speed;
217 + char etabuf[64];
218 + time_t t_temp;
219 +
220 + sample_window[sample_count - 1] = (n_read_total - last_bytes) /
221 + (t_now - t_last);
222 + sample_sum += sample_window[sample_count - 1];
223 +
224 + /* Calculate the remaining time */
225 + t_temp = (src_open_sb.st_size - n_read_total) / (sample_sum / sample_count);
226 +
227 + /* Don't print the progress bar if the estimated remaining
228 + time is low. */
229 + if (progress_bar_printed == 1 && t_temp < x->pbar_min_est)
230 + {
231 + continue;
232 + }
233 + progress_bar_printed = 2;
234 +
235 + str_size = si_units(src_open_sb.st_size);
236 + str_speed = si_units(sample_sum / sample_count);
237 +
238 + strftime(etabuf, sizeof etabuf, "%H:%M.%S",
239 + gmtime(&t_temp));
240 + printf (_("%s | %3lu%% | %9s | %9s/s | ETA %s\r"), shortname,
241 + (unsigned long)(n_read_total * 100 / src_open_sb.st_size),
242 + str_size, str_speed, etabuf);
243 + fflush (stdout);
244 + free(str_size);
245 + free(str_speed);
246 + t_last = t_now;
247 + last_bytes = n_read_total;
248 + }
249 + }
250 +
251 + /* Print a newline if progress bar is enabled and has been shown */
252 + if (progress_bar_printed == 2)
253 + {
254 + printf ("%s | 100%%\n", shortname);
255 }
256
257 /* If the file ends with a `hole', something needs to be written at
258 @@ -488,6 +676,11 @@ close_src_desc:
259 return_val = false;
260 }
261
262 + if (shortname != NULL)
263 + {
264 + free (shortname);
265 + }
266 +
267 return return_val;
268 }
269
270 --- coreutils/src/copy.h
271 +++ coreutils/src/copy.h
272 @@ -175,6 +175,16 @@ struct cp_options
273 /* If true, display the names of the files before copying them. */
274 bool verbose;
275
276 + /* If true, display a progress bar when the following conditions are
277 + * met:
278 + - pbar_delay defines how many seconds to wait before considering to
279 + display the progress bar
280 + - pbar_min_est defines how many seconds estimated operation complete
281 + time should be at least to show the progress bar. */
282 + bool pbar_show;
283 + int pbar_delay;
284 + int pbar_min_est;
285 +
286 /* If true, stdin is a tty. */
287 bool stdin_tty;
288
289 --- coreutils/src/cp.c
290 +++ coreutils/src/cp.c
291 @@ -81,6 +81,14 @@ enum
292 /* Initial number of entries in the inode hash table. */
293 #define INITIAL_ENTRY_TAB_SIZE 70
294
295 +/* Initial settings for progress bar when it's enabled.
296 + PROGRESS_DELAY defines how many seconds to wait before even
297 + considering to display a proggress bar.
298 + PROGRESS_MIN_EST defines how many seconds estimated operation
299 + complete time should be at least to show the progress bar. */
300 +#define PROGRESS_DELAY 5
301 +#define PROGRESS_MIN_EST 5
302 +
303 /* The invocation name of this program. */
304 char *program_name;
305
306 @@ -120,6 +128,7 @@ static struct option const long_opts[] =
307 {"copy-contents", no_argument, NULL, COPY_CONTENTS_OPTION},
308 {"dereference", no_argument, NULL, 'L'},
309 {"force", no_argument, NULL, 'f'},
310 + {"progress", no_argument, NULL, 'g'},
311 {"interactive", no_argument, NULL, 'i'},
312 {"link", no_argument, NULL, 'l'},
313 {"no-dereference", no_argument, NULL, 'P'},
314 @@ -176,6 +185,8 @@ Mandatory arguments to long options are
315 fputs (_("\
316 -f, --force if an existing destination file cannot be\n\
317 opened, remove it and try again\n\
318 + -g, --progress show a progress bar if operation is going to\n\
319 + take a long time\n\
320 -i, --interactive prompt before overwrite\n\
321 -H follow command-line symbolic links\n\
322 "), stdout);
323 @@ -705,6 +716,11 @@ cp_option_init (struct cp_options *x)
324
325 x->update = false;
326 x->verbose = false;
327 +
328 + x->pbar_show = false;
329 + x->pbar_delay = PROGRESS_DELAY;
330 + x->pbar_min_est = PROGRESS_MIN_EST;
331 +
332 x->dest_info = NULL;
333 x->src_info = NULL;
334 }
335 @@ -811,7 +827,7 @@ main (int argc, char **argv)
336 we'll actually use backup_suffix_string. */
337 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
338
339 - while ((c = getopt_long (argc, argv, "abdfHilLprst:uvxPRS:T",
340 + while ((c = getopt_long (argc, argv, "abdfgHilLprst:uvxPRS:T",
341 long_opts, NULL))
342 != -1)
343 {
344 @@ -871,6 +887,10 @@ main (int argc, char **argv)
345 x.dereference = DEREF_NEVER;
346 break;
347
348 + case 'g':
349 + x.pbar_show = 1;
350 + break;
351 +
352 case NO_PRESERVE_ATTRIBUTES_OPTION:
353 decode_preserve_arg (optarg, &x, false);
354 break;
355 --- coreutils/src/mv.c
356 +++ coreutils/src/mv.c
357 @@ -45,6 +45,14 @@
358 /* Initial number of entries in the inode hash table. */
359 #define INITIAL_ENTRY_TAB_SIZE 70
360
361 +/* Initial settings for progress bar when it's enabled.
362 + PROGRESS_DELAY defines how many seconds to wait before even
363 + considering to display a proggress bar.
364 + PROGRESS_MIN_EST defines how many seconds estimated operation
365 + complete time should be at least to show the progress bar. */
366 +#define PROGRESS_DELAY 5
367 +#define PROGRESS_MIN_EST 5
368 +
369 /* For long options that have no equivalent short option, use a
370 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
371 enum
372 @@ -75,6 +83,7 @@ static struct option const long_options[
373 {
374 {"backup", optional_argument, NULL, 'b'},
375 {"force", no_argument, NULL, 'f'},
376 + {"progress", no_argument, NULL, 'g'},
377 {"interactive", no_argument, NULL, 'i'},
378 {"no-target-directory", no_argument, NULL, 'T'},
379 {"reply", required_argument, NULL, REPLY_OPTION}, /* Deprecated 2005-07-03,
380 @@ -104,6 +113,10 @@ rm_option_init (struct rm_options *x)
381
382 x->verbose = false;
383
384 + x->pbar_show = false;
385 + x->pbar_delay = PROGRESS_DELAY;
386 + x->pbar_min_est = PROGRESS_MIN_EST;
387 +
388 /* Since this program may well have to process additional command
389 line arguments after any call to `rm', that function must preserve
390 the initial working directory, in case one of those is a
391 @@ -312,6 +325,8 @@ Mandatory arguments to long options are
392 --backup[=CONTROL] make a backup of each existing destination file\n\
393 -b like --backup but does not accept an argument\n\
394 -f, --force do not prompt before overwriting\n\
395 + -g, --progress show a progress bar if operation is going to\n\
396 + take a long time\n\
397 -i, --interactive prompt before overwrite\n\
398 "), stdout);
399 fputs (_("\
400 @@ -375,7 +393,7 @@ main (int argc, char **argv)
401 we'll actually use backup_suffix_string. */
402 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
403
404 - while ((c = getopt_long (argc, argv, "bfit:uvS:T", long_options, NULL))
405 + while ((c = getopt_long (argc, argv, "bfgit:uvS:T", long_options, NULL))
406 != -1)
407 {
408 switch (c)
409 @@ -388,6 +406,9 @@ main (int argc, char **argv)
410 case 'f':
411 x.interactive = I_ALWAYS_YES;
412 break;
413 + case 'g':
414 + x.pbar_show = 1;
415 + break;
416 case 'i':
417 x.interactive = I_ASK_USER;
418 break;
419 --- coreutils/src/remove.h
420 +++ coreutils/src/remove.h
421 @@ -48,6 +48,16 @@ struct rm_options
422 /* If true, display the name of each file removed. */
423 bool verbose;
424
425 + /* If true, display a progress bar when the following conditions are
426 + * met:
427 + - pbar_delay defines how many seconds to wait before considering to
428 + display the progress bar
429 + - pbar_min_est defines how many seconds estimated operation complete
430 + time should be at least to show the progress bar. */
431 + bool pbar_show;
432 + int pbar_delay;
433 + int pbar_min_est;
434 +
435 /* If true, treat the failure by the rm function to restore the
436 current working directory as a fatal error. I.e., if this field
437 is true and the rm function cannot restore cwd, it must exit with