Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 niro 115 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