]> git.pld-linux.org Git - packages/coreutils.git/blob - coreutils-advcopy.patch
- fix this patch a bit, add -g,--progress-bar options which are per default disabled
[packages/coreutils.git] / coreutils-advcopy.patch
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
4 @@ -457,6 +457,56 @@
5    return lchmod (name, mode);
6  }
7  
8 +/* BEGIN progress mod */
9 +static void file_progress_bar ( char * _cDest, int _iBarLength, int _iProgress, int _iTotal )
10 +{
11 +  // write number to progress bar
12 +  float fPercent = ( float ) _iProgress / ( float ) _iTotal * 100.f;
13 +  sprintf ( _cDest + ( _iBarLength - 6 ), "%4.1f", fPercent );
14 +  // remove zero
15 +  _cDest[_iBarLength - 2] = ' ';
16 +  
17 +  // fill rest with '-'
18 +  int i;
19 +  for ( i = 1; i <= _iBarLength - 9; i++ )
20 +  {
21 +    if ( fPercent > ( float ) ( i - 1 ) / ( _iBarLength - 10 ) * 100.f )
22 +      _cDest[i] = '|';
23 +    else
24 +      _cDest[i] = '-';
25 +  }
26 +}
27 +
28 +int file_size_format ( char * _cDst, int _iSize, int _iCounter )
29 +{
30 +  int iCounter = _iCounter;
31 +  double dSize = ( double ) _iSize;
32 +  while ( dSize >= 1000. )
33 +  {
34 +    dSize /= 1024.;
35 +    iCounter++;
36 +  }
37 +  
38 +  /* get unit */
39 +  char * sUnit;
40 +  if ( iCounter == 0 )
41 +    sUnit = "B";
42 +  else if ( iCounter == 1 )
43 +    sUnit = "KiB";
44 +  else if ( iCounter == 2 )
45 +    sUnit = "MiB";
46 +  else if ( iCounter == 3 )
47 +    sUnit = "GiB";
48 +  else if ( iCounter == 4 )
49 +    sUnit = "TiB";
50 +  else
51 +    sUnit = "N/A";
52 +
53 +  /* write number */
54 +  return sprintf ( _cDst, "%5.1f %s", dSize, sUnit );
55 +}
56 +/* END progress mod */
57 +
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.
61 @@ -630,7 +680,7 @@
62        return_val = false;
63        goto close_src_and_dst_desc;
64      }
65 -
66 +  
67    if (x->reflink_mode)
68      {
69        bool clone_ok = clone_file (dest_desc, source_desc) == 0;
70 @@ -706,8 +756,112 @@
71        buf_alloc = xmalloc (buf_size + buf_alignment_slop);
72        buf = ptr_align (buf_alloc, buf_alignment);
73  
74 +      int it;
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 */
80 +      struct winsize win;
81 +      if ( ioctl (STDOUT_FILENO, TIOCGWINSZ, (char *) &win) == 0 && win.ws_col > 0 )
82 +         iBarLength = win.ws_col;
83 +      /* create rows */
84 +      for ( it = 0; it < 6; it++ )
85 +      {
86 +        cProgressField[it] = ( char * ) malloc ( iBarLength + 1 );
87 +        /* init with spaces */
88 +        int j;
89 +        for ( j = 0; j < iBarLength; j++ )
90 +          cProgressField[it][j] = ' ';
91 +        cProgressField[it][iBarLength] = '\0';
92 +      }
93 +      
94 +      /* global progress bar? */
95 +      if ( g_iTotalSize )
96 +      {
97 +        /* init global progress bar */
98 +        cProgressField[2][0] = '[';
99 +        cProgressField[2][iBarLength - 8] = ']';
100 +        cProgressField[2][iBarLength - 7] = ' ';
101 +        cProgressField[2][iBarLength - 1] = '%';
102 +        
103 +        /* total size */
104 +        cProgressField[1][iBarLength - 11] = '/';
105 +        file_size_format ( cProgressField[1] + iBarLength - 9, g_iTotalSize, 1 );
106 +        
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] = ' ';
110 +      }
111 +      
112 +      /* truncate filename? */
113 +      int fn_length;
114 +      if ( strlen ( src_name ) > iBarLength - 22 )
115 +        fn_length =
116 +          sprintf ( cProgressField[4], "...%s", src_name + ( strlen ( src_name ) - iBarLength + 25 ) );
117 +      else
118 +        fn_length = sprintf ( cProgressField[4], "%s", src_name );
119 +      cProgressField[4][fn_length] = ' ';
120 +      
121 +      /* filesize */
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;
131 +      
132        for (;;)
133          {
134 +          if (progress) {
135 +          /* BEGIN progress mod */
136 +          /* update countdown */
137 +          iCountDown--;
138 +          if ( iCountDown < 0 )
139 +            iCountDown = 100;
140 +          
141 +          /* just print one line with the percentage, but not always */
142 +          if ( iCountDown == 0 )
143 +          {
144 +            int fs_len;
145 +            if ( g_iTotalSize )
146 +            {
147 +              /* global progress bar */
148 +              file_progress_bar ( cProgressField[2], iBarLength,
149 +                                  g_iTotalWritten + n_read_total / 1024, g_iTotalSize );
150 +              
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] = ' ';
155 +            }
156 +            
157 +            /* current progress bar */
158 +            file_progress_bar ( sProgressBar, iBarLength, n_read_total, src_open_sb.st_size );
159 +            
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] = ' ';
163 +            
164 +            /* print the field */
165 +            for ( it = g_iTotalSize ? 0 : 3; it < 6; it++ )
166 +            {
167 +              printf ( "%s\n", cProgressField[it] );
168 +              if ( strlen ( cProgressField[it] ) < iBarLength )
169 +                printf ( "" );
170 +            }
171 +            if ( g_iTotalSize )
172 +              printf ( "\r\033[6A" );
173 +            else
174 +              printf ( "\r\033[3A" );
175 +            fflush ( stdout );
176 +          }
177 +          /* END progress mod */
178 +          }
179 +          
180            word *wp = NULL;
181  
182            ssize_t n_read = read (source_desc, buf, buf_size);
183 @@ -788,6 +942,19 @@
184                   /proc with linux kernels from at least 2.6.9 .. 2.6.29.  */
185              }
186          }
187 +if (progress) {
188 +      /* BEGIN progress mod */
189 +      /* update total size */
190 +      g_iTotalWritten += n_read_total / 1024;
191 +      g_iFilesCopied++;
192 +       
193 +      int i;
194 +      for ( i = 0; i < 6; i++ )
195 +        free ( cProgressField[i] );
196 +      free ( cProgressField );
197 +      /* END progress mod */
198 +}
199 +
200  
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
206 @@ -222,6 +222,9 @@
207       Create destination directories as usual. */
208    bool symbolic_link;
209  
210 +  /* if true, draw a nice progress bar on screen */
211 +  bool progress_bar;
212 +
213    /* If true, do not copy a nondirectory that has an existing destination
214       with the same or newer modification time. */
215    bool update;
216 @@ -280,4 +283,13 @@
217  bool chown_failure_ok (struct cp_options const *);
218  mode_t cached_umask (void);
219  
220 +/* BEGIN progress mod */
221 +int file_size_format ( char * _cDst, int _iSize, int _iCounter );
222 +
223 +long g_iTotalSize;
224 +long g_iTotalWritten;
225 +int g_iFilesCopied;
226 +bool progress;
227 +/* END progress mod */
228 +
229  #endif
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
233 @@ -139,6 +139,7 @@
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},
240    {NULL, 0, NULL, 0}
241 @@ -176,6 +177,7 @@
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\
247                                    option)\n\
248    -H                           follow command-line symbolic links in SOURCE\n\
249 @@ -611,6 +613,18 @@
250          error (EXIT_FAILURE, 0, _("target %s is not a directory"),
251                 quote (file[n_files - 1]));
252      }
253 +   
254 +    struct timeval start_time;
255 +if (progress) { 
256 +    /* BEGIN progress mod */
257 +    g_iTotalSize = 0;
258 +    g_iFilesCopied = 0;
259 +    g_iTotalWritten = 0;
260 +    
261 +    /* save time */
262 +    gettimeofday ( & start_time, NULL );
263 +    /* END progress mod */
264 +}
265  
266    if (target_directory)
267      {
268 @@ -627,6 +641,46 @@
269            dest_info_init (x);
270            src_info_init (x);
271          }
272 +        
273 +if (progress) { 
274 +      /* BEGIN progress mod */
275 +      printf ( "Calculating total size... \r" );
276 +      fflush ( stdout );
277 +      long iTotalSize = 0;
278 +      for (i = 0; i < n_files; i++)
279 +      {
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] */
285 +        
286 +        FILE *fp;
287 +        char output[1024];
288 +
289 +        /* run command */
290 +        fp = popen(command, "r");
291 +        if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) {
292 +          printf("failed to run du.\n" );
293 +        }
294 +        else
295 +        {
296 +          /* isolate size */
297 +          strchr ( output, '\t' )[0] = '\0';
298 +          iTotalSize += atol ( output );
299 +          
300 +          printf ( "Calculating total size... %d\r", iTotalSize );
301 +          fflush ( stdout );
302 +        }
303 +        
304 +        /* close */
305 +        pclose(fp);
306 +      }
307 +      g_iTotalSize = iTotalSize;
308 +      g_iTotalWritten = 0;
309 +      g_iFilesCopied = 0;
310 +      /* END progress mod */
311 +}
312  
313        for (i = 0; i < n_files; i++)
314          {
315 @@ -753,6 +807,46 @@
316  
317        ok = copy (source, new_dest, 0, x, &unused, NULL);
318      }
319 +    
320 +if (progress) { 
321 +    /* BEGIN progress mod */
322 +    /* remove everything */
323 +    int i;
324 +    if ( g_iTotalSize )
325 +    {
326 +      for ( i = 0; i < 6; i++ )
327 +        printf ( "\033[K\n" );
328 +      printf ( "\r\033[6A" );
329 +    }
330 +    else
331 +    {
332 +      for ( i = 0; i < 3; i++ )
333 +        printf ( "\033[K\n" );
334 +      printf ( "\r\033[3A" );
335 +    }
336 +    
337 +    /* save time */
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 );
343 +    
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 */
348 +    
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 );
353 +    
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 */
358 +}
359  
360    return ok;
361  }
362 @@ -785,6 +879,7 @@
363    x->recursive = false;
364    x->sparse_mode = SPARSE_AUTO;
365    x->symbolic_link = false;
366 +  x->progress_bar = false;
367    x->set_mode = false;
368    x->mode = 0;
369  
370 @@ -923,7 +1018,7 @@
371       we'll actually use backup_suffix_string.  */
372    backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
373  
374 -  while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:T",
375 +  while ((c = getopt_long (argc, argv, "abdfgHilLnprst:uvxPRS:T",
376                             long_opts, NULL))
377           != -1)
378      {
379 @@ -974,6 +1069,10 @@
380          case 'f':
381            x.unlink_dest_after_failed_open = true;
382            break;
383 +       
384 +        case 'g':
385 +          progress = true;
386 +          break;
387  
388          case 'H':
389            x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
390 @@ -1043,6 +1142,7 @@
391            x.symbolic_link = true;
392            break;
393  
394 +
395          case 't':
396            if (target_directory)
397              error (EXIT_FAILURE, 0,
This page took 0.066949 seconds and 3 git commands to generate.