Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show annotations) (download)
Thu Oct 13 21:17:16 2005 UTC (18 years, 7 months ago) by niro
File size: 12049 byte(s)
patch set for coretutils-5.3.0

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 diff -urN 1/src/copy.c 2/src/copy.c
13 --- 1/src/copy.c 2004-09-20 08:27:12.000000000 +0100
14 +++ 2/src/copy.c 2005-03-26 15:53:57.000000000 +0000
15 @@ -17,6 +17,8 @@
16
17 /* Extracted from cp.c and librarified by Jim Meyering. */
18
19 +/* Progress bar support added by Miika Pekkarinen. miipekk@ihme.org */
20 +
21 #include <config.h>
22 #include <stdio.h>
23 #include <assert.h>
24 @@ -26,6 +28,10 @@
25 # include <hurd.h>
26 #endif
27
28 +#ifdef GWINSZ_IN_SYS_IOCTL
29 +# include <sys/ioctl.h>
30 +#endif
31 +
32 #include "system.h"
33 #include "backupfile.h"
34 #include "copy.h"
35 @@ -44,3 +50,4 @@
36 #include "savedir.h"
37 #include "utimens.h"
38 +#include "xstrtol.h"
39 #include "xreadlink.h"
40 @@ -80,6 +87,8 @@
41 /* Initial size of the above hash table. */
42 #define DEST_INFO_INITIAL_CAPACITY 61
43
44 +#define SAMPLE_MAX 10
45 +
46 static bool copy_internal (const char *src_path, const char *dst_path,
47 bool new_dst, dev_t device,
48 struct dir_list *ancestors,
49 @@ -186,6 +195,62 @@
50 return ok;
51 }
52
53 +/* Shorten a string '/long path/long file' to 'long fi...'
54 + Also adds padding bytes to end of the string if necessary */
55 +char *shorten_path(const char *str, int max_width)
56 +{
57 + char *shortname;
58 + char *filename = (char *) (rindex(str, '/'));
59 + int len;
60 +
61 + if (filename == NULL)
62 + {
63 + filename = (char *) str;
64 + }
65 + else
66 + {
67 + filename = (char *) &filename[1];
68 + }
69 +
70 + len = strlen(filename);
71 + shortname = (char *) xmalloc (max_width + 1);
72 + strncpy (shortname, filename, max_width);
73 + shortname[max_width] = '\0';
74 + if (len > max_width)
75 + {
76 + memset(&shortname[max_width - 3], '.', 3);
77 + }
78 + else
79 + {
80 + memset(&shortname[len], ' ', max_width - len);
81 + }
82 +
83 + return shortname;
84 +}
85 +
86 +char *si_units(off_t size)
87 +{
88 + const static int buf_size = 20;
89 + char *buf;
90 + static char *unit_array[] = { "B", "KiB", "MiB", "GiB", "" };
91 + int i;
92 +
93 + buf = xmalloc(20);
94 + for (i = 0; size > 10000; i++)
95 + {
96 + if (unit_array[i][0] == '\0')
97 + {
98 + i--;
99 + break;
100 + }
101 + size /= 1024;
102 + }
103 +
104 + snprintf (buf, buf_size, "%lu %s", (unsigned long)size, unit_array[i]);
105 +
106 + return buf;
107 +}
108 +
109 /* Copy a regular file from SRC_PATH to DST_PATH.
110 If the source file contains holes, copies holes and blocks of zeros
111 in the source file as holes in the destination file.
112 @@ -214,6 +279,19 @@
113 off_t n_read_total = 0;
114 bool last_write_made_hole = false;
115 bool make_holes = false;
116 + time_t t_start;
117 + time_t t_last;
118 + time_t t_now;
119 + int last_bytes = 0;
120 + int progress_bar_printed = 0;
121 + char *shortname = NULL;
122 + off_t sample_window[SAMPLE_MAX];
123 + off_t sample_sum = 0;
124 + int sample_count = 0;
125 + int line_length = 0;
126 +#ifdef TIOCGWINSZ
127 + struct winsize ws;
128 +#endif
129
130 source_desc = open (src_path, O_RDONLY);
131 if (source_desc < 0)
132 @@ -318,6 +396,9 @@
133 buf = alloca (buf_size + sizeof (int) + buf_alignment - 1);
134 buf = ptr_align (buf, buf_alignment);
135
136 + time (&t_start);
137 + t_last = t_start;
138 +
139 for (;;)
140 {
141 ssize_t n_read = read (source_desc, buf, buf_size);
142 @@ -382,6 +463,113 @@
143 }
144 last_write_made_hole = false;
145 }
146 +
147 + time (&t_now);
148 +
149 + /* Progress bar stuff */
150 + if (! x->pbar_show || t_now - t_start < x->pbar_delay)
151 + {
152 + continue;
153 + }
154 +
155 + if (! progress_bar_printed)
156 + {
157 + /* Column width check code copied from ls.c */
158 + char const *p = getenv ("COLUMNS");
159 + if (p && *p)
160 + {
161 + long int tmp_long;
162 + if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
163 + && 0 < tmp_long && tmp_long <= INT_MAX)
164 + {
165 + line_length = (int) tmp_long;
166 + }
167 + else
168 + {
169 + error (0, 0,
170 + _("ignoring invalid width in environment \
171 + variable COLUMNS: %s"),
172 + quotearg (p));
173 + }
174 + }
175 +
176 +#ifdef TIOCGWINSZ
177 + if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
178 + {
179 + line_length = ws.ws_col;
180 + }
181 +#endif
182 + if (line_length < 50)
183 + {
184 + continue;
185 + }
186 +
187 + /* Take a short filename for progress bar */
188 + shortname = shorten_path(src_path, line_length - 48);
189 + progress_bar_printed = 1;
190 + }
191 +
192 + if (t_now == t_last)
193 + {
194 + continue;
195 + }
196 +
197 + if (sample_count == SAMPLE_MAX)
198 + {
199 + int i;
200 +
201 + sample_sum -= sample_window[0];
202 + for (i = 0; i < SAMPLE_MAX - 1; i++)
203 + {
204 + sample_window[i] = sample_window[i + 1];
205 + }
206 + }
207 + else
208 + {
209 + sample_count++;
210 + }
211 +
212 + {
213 + char *str_size;
214 + char *str_speed;
215 + char etabuf[64];
216 + time_t t_temp;
217 +
218 + sample_window[sample_count - 1] = (n_read_total - last_bytes) /
219 + (t_now - t_last);
220 + sample_sum += sample_window[sample_count - 1];
221 +
222 + /* Calculate the remaining time */
223 + t_temp = (src_open_sb.st_size - n_read_total) / (sample_sum / sample_count);
224 +
225 + /* Don't print the progress bar if the estimated remaining
226 + time is low. */
227 + if (progress_bar_printed == 1 && t_temp < x->pbar_min_est)
228 + {
229 + continue;
230 + }
231 + progress_bar_printed = 2;
232 +
233 + str_size = si_units(src_open_sb.st_size);
234 + str_speed = si_units(sample_sum / sample_count);
235 +
236 + strftime(etabuf, sizeof etabuf, "%H:%M.%S",
237 + gmtime(&t_temp));
238 + printf (_("%s | %3d%% | %9s | %9s/s | ETA %s\r"), shortname,
239 + (int)(n_read_total * 100 / src_open_sb.st_size),
240 + str_size, str_speed, etabuf);
241 + fflush (stdout);
242 + free(str_size);
243 + free(str_speed);
244 + t_last = t_now;
245 + last_bytes = n_read_total;
246 + }
247 + }
248 +
249 + /* Print a newline if progress bar is enabled and has been shown */
250 + if (progress_bar_printed == 2)
251 + {
252 + printf ("%s | 100%%\n", shortname);
253 }
254
255 /* If the file ends with a `hole', something needs to be written at
256 @@ -418,6 +606,11 @@
257 return_val = false;
258 }
259
260 + if (shortname != NULL)
261 + {
262 + free (shortname);
263 + }
264 +
265 return return_val;
266 }
267
268 diff -urN 1/src/copy.h 2/src/copy.h
269 --- 1/src/copy.h 2004-11-26 09:03:45.000000000 +0000
270 +++ 2/src/copy.h 2005-03-26 15:44:50.000000000 +0000
271 @@ -154,6 +154,16 @@
272 /* If true, display the names of the files before copying them. */
273 bool verbose;
274
275 + /* If true, display a progress bar when the following conditions are
276 + * met:
277 + - pbar_delay defines how many seconds to wait before considering to
278 + display the progress bar
279 + - pbar_min_est defines how many seconds estimated operation complete
280 + time should be at least to show the progress bar. */
281 + bool pbar_show;
282 + int pbar_delay;
283 + int pbar_min_est;
284 +
285 /* If true, stdin is a tty. */
286 bool stdin_tty;
287
288 diff -urN 1/src/cp.c 2/src/cp.c
289 --- 1/src/cp.c 2004-10-10 20:10:09.000000000 +0100
290 +++ 2/src/cp.c 2005-03-26 15:46:00.000000000 +0000
291 @@ -84,6 +84,14 @@
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 @@ -123,6 +131,7 @@
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 @@ -180,6 +189,8 @@
315 --no-dereference never follow symbolic links\n\
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 @@ -711,6 +722,11 @@
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 @@ -817,7 +833,7 @@
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:TV:",
340 + while ((c = getopt_long (argc, argv, "abdfgHilLprst:uvxPRS:TV:",
341 long_opts, NULL))
342 != -1)
343 {
344 @@ -887,6 +903,10 @@
345 case NO_PRESERVE_ATTRIBUTES_OPTION:
346 decode_preserve_arg (optarg, &x, false);
347 break;
348 +
349 + case 'g':
350 + x.pbar_show = 1;
351 + break;
352
353 case PRESERVE_ATTRIBUTES_OPTION:
354 if (optarg == NULL)
355 diff -urN 1/src/mv.c 2/src/mv.c
356 --- 1/src/mv.c 2004-09-22 13:41:20.000000000 +0100
357 +++ 2/src/mv.c 2005-03-26 15:48:35.000000000 +0000
358 @@ -45,6 +45,14 @@
359 /* Initial number of entries in the inode hash table. */
360 #define INITIAL_ENTRY_TAB_SIZE 70
361
362 +/* Initial settings for progress bar when it's enabled.
363 + PROGRESS_DELAY defines how many seconds to wait before even
364 + considering to display a proggress bar.
365 + PROGRESS_MIN_EST defines how many seconds estimated operation
366 + complete time should be at least to show the progress bar. */
367 +#define PROGRESS_DELAY 5
368 +#define PROGRESS_MIN_EST 5
369 +
370 /* For long options that have no equivalent short option, use a
371 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
372 enum
373 @@ -75,6 +83,7 @@
374 {
375 {"backup", optional_argument, NULL, 'b'},
376 {"force", no_argument, NULL, 'f'},
377 + {"progress", no_argument, NULL, 'g'},
378 {"interactive", no_argument, NULL, 'i'},
379 {"no-target-directory", no_argument, NULL, 'T'},
380 {"reply", required_argument, NULL, REPLY_OPTION},
381 @@ -143,6 +152,10 @@
382
383 x->update = false;
384 x->verbose = false;
385 + x->pbar_show = false;
386 + x->pbar_delay = PROGRESS_DELAY;
387 + x->pbar_min_est = PROGRESS_MIN_EST;
388 +
389 x->dest_info = NULL;
390 x->src_info = NULL;
391 }
392 @@ -313,6 +326,8 @@
393 -b like --backup but does not accept an argument\n\
394 -f, --force do not prompt before overwriting\n\
395 (equivalent to --reply=yes)\n\
396 + -g, --progress show a progress bar if operation is going to\n\
397 + take a long time\n\
398 -i, --interactive prompt before overwrite\n\
399 (equivalent to --reply=query)\n\
400 "), stdout);
401 @@ -357,6 +372,9 @@
402 int c;
403 bool ok;
404 bool make_backups = false;
405 + bool pbar_show = false;
406 + int pbar_delay = PROGRESS_DELAY;
407 + int pbar_min_est = PROGRESS_MIN_EST;
408 char *backup_suffix_string;
409 char *version_control_string = NULL;
410 struct cp_options x;
411 @@ -379,7 +397,7 @@
412 we'll actually use backup_suffix_string. */
413 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
414
415 - while ((c = getopt_long (argc, argv, "bfit:uvS:TV:", long_options, NULL))
416 + while ((c = getopt_long (argc, argv, "bfgit:uvS:TV:", long_options, NULL))
417 != -1)
418 {
419 switch (c)
420 @@ -399,6 +417,9 @@
421 case 'f':
422 x.interactive = I_ALWAYS_YES;
423 break;
424 + case 'g':
425 + x.pbar_show = 1;
426 + break;
427 case 'i':
428 x.interactive = I_ASK_USER;
429 break;