]>
Commit | Line | Data |
---|---|---|
b09470a3 MK |
1 | diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c |
2 | --- coreutils-9.0/src/copy.c 2021-09-24 17:01:05.000000000 +0530 | |
3 | +++ coreutils-9.0-patched/src/copy.c 2022-03-27 05:54:15.840209369 +0530 | |
4 | @@ -129,6 +129,133 @@ | |
e79174a7 AM |
5 | dev_t dev; |
6 | }; | |
7 | ||
b09470a3 | 8 | +/* BEGIN progress mod */ |
e79174a7 AM |
9 | +struct progress_status { |
10 | + int iCountDown; | |
11 | + char ** cProgressField; | |
12 | + struct timeval last_time; | |
13 | + int last_size, iBarLength; | |
14 | + struct stat src_open_sb; | |
15 | +}; | |
16 | + | |
b09470a3 MK |
17 | +FILE * spawn( const char *cmd, char *const argv[] ) |
18 | +{ | |
19 | + FILE *ret = NULL; | |
20 | + int pfd_read[2]; | |
21 | + pid_t pid; | |
22 | + | |
23 | + if (cmd == NULL || argv == NULL) | |
24 | + return ret; | |
25 | + | |
26 | + if (pipe(pfd_read) < 0) { | |
27 | + error(0, errno, "pipe: %s", cmd); | |
28 | + return ret; | |
29 | + } | |
30 | + | |
31 | + if ((pid = fork()) == 0) { | |
32 | + int err = dup2(pfd_read[1], 1) < 0; | |
33 | + close(pfd_read[0]); | |
34 | + close(pfd_read[1]); | |
35 | + | |
36 | + if (err) | |
37 | + error(EXIT_FAILURE, errno, "dup2: %s", cmd); | |
38 | + execvp(cmd, argv); | |
39 | + error(EXIT_FAILURE, errno, "exec: %s", cmd); | |
40 | + } | |
41 | + | |
42 | + close(pfd_read[1]); | |
43 | + | |
44 | + if (pid < 0) { | |
45 | + close(pfd_read[0]); | |
46 | + error(0, errno, "fork: %s", cmd); | |
47 | + return ret; | |
48 | + } | |
49 | + | |
50 | + ret = fdopen(pfd_read[0], "r"); | |
51 | + return ret; | |
52 | +} | |
53 | + | |
54 | +void format_time ( char * _cDest, double seconds, bool showall ) | |
55 | +{ | |
56 | + // hours | |
57 | + int hr = ( (int) seconds / (60 * 60)) % 24; | |
58 | + // minutes | |
59 | + int min = ( (int) seconds / 60) % 60; | |
60 | + // seconds | |
61 | + double sec = seconds - (hr * (60 * 60)) - (min * 60); | |
62 | + if ( showall ) | |
63 | + { | |
64 | + if ( seconds < 0 ) | |
65 | + sprintf(_cDest, "%2ch %2cm %2cs", '0', '0', '?'); | |
66 | + else | |
67 | + sprintf(_cDest, "%2dh %2dm %2ds", hr, min, (int) sec); | |
68 | + } else if ( seconds >= 3600 ) | |
69 | + { | |
70 | + sprintf(_cDest, "%2dh %2dm %4.1fs", hr, min, sec); | |
71 | + } else if ( seconds >= 60 ) | |
72 | + { | |
73 | + sprintf(_cDest, "%2dm %4.1fs", min, sec); | |
74 | + } else | |
75 | + { | |
76 | + sprintf(_cDest, "%4.1fs", sec); | |
77 | + } | |
78 | +} | |
79 | + | |
e79174a7 AM |
80 | +static void file_progress_bar ( char * _cDest, int _iBarLength, long _lProgress, long _lTotal ) |
81 | +{ | |
82 | + double dPercent = (double) _lProgress / (double) _lTotal * 100.f; | |
83 | + sprintf( _cDest + ( _iBarLength - 6), "%4.1f", dPercent ); | |
84 | + _cDest[_iBarLength - 2] = ' '; | |
85 | + | |
86 | + int i; | |
87 | + for ( i=1; i<=_iBarLength - 9; i++) | |
88 | + { | |
89 | + if ( dPercent > (double) (i-1) / (_iBarLength - 10) * 100.f ) | |
90 | + { | |
91 | + _cDest[i] = '='; | |
92 | + } | |
93 | + else | |
94 | + { | |
95 | + _cDest[i] = ' '; | |
96 | + } | |
97 | + } | |
98 | + for ( i=1; i<_iBarLength - 9; i++) | |
99 | + { | |
100 | + if ( ( _cDest[i+1] == ' ' ) && ( _cDest[i] == '=' ) ) | |
101 | + _cDest[i] = '>' ; | |
102 | + } | |
103 | +} | |
104 | + | |
105 | +int file_size_format ( char * _cDst, long _lSize, int _iCounter ) | |
106 | +{ | |
107 | + int iCounter = _iCounter; | |
108 | + double dSize = ( double ) _lSize; | |
109 | + while ( dSize >= 1000. ) | |
110 | + { | |
111 | + dSize /= 1024.; | |
112 | + iCounter++; | |
113 | + } | |
114 | + | |
115 | + /* get unit */ | |
116 | + char * sUnit; | |
117 | + if ( iCounter == 0 ) | |
118 | + sUnit = "B"; | |
119 | + else if ( iCounter == 1 ) | |
120 | + sUnit = "KiB"; | |
121 | + else if ( iCounter == 2 ) | |
122 | + sUnit = "MiB"; | |
123 | + else if ( iCounter == 3 ) | |
124 | + sUnit = "GiB"; | |
125 | + else if ( iCounter == 4 ) | |
126 | + sUnit = "TiB"; | |
127 | + else | |
128 | + sUnit = "N/A"; | |
129 | + | |
130 | + /* write number */ | |
131 | + return sprintf ( _cDst, "%5.1f %s", dSize, sUnit ); | |
132 | +} | |
133 | +/* END progress mod */ | |
e79174a7 AM |
134 | + |
135 | /* Initial size of the cp.dest_info hash table. */ | |
136 | #define DEST_INFO_INITIAL_CAPACITY 61 | |
137 | ||
b09470a3 | 138 | @@ -299,14 +426,23 @@ |
e79174a7 AM |
139 | bytes read. */ |
140 | static bool | |
141 | sparse_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, | |
b09470a3 MK |
142 | - size_t hole_size, bool punch_holes, bool allow_reflink, |
143 | + size_t hole_size, bool punch_holes, bool allow_reflink, bool move_mode, | |
e79174a7 AM |
144 | char const *src_name, char const *dst_name, |
145 | uintmax_t max_n_read, off_t *total_n_read, | |
146 | - bool *last_write_made_hole) | |
147 | + bool *last_write_made_hole, | |
148 | + struct progress_status *s_progress) | |
149 | { | |
150 | *last_write_made_hole = false; | |
151 | *total_n_read = 0; | |
b09470a3 MK |
152 | |
153 | + /* BEGIN progress mod */ | |
154 | + gettimeofday ( & g_oFStartTime, NULL ); | |
155 | + g_iFTotalWritten = 0; | |
156 | + struct stat st; | |
157 | + stat(src_name, &st); | |
158 | + g_iFTotalSize = st.st_size/1024; | |
159 | + /* END progress mod */ | |
160 | + | |
161 | /* If not looking for holes, use copy_file_range if functional, | |
162 | but don't use if reflink disallowed as that may be implicit. */ | |
163 | if ((! hole_size) && allow_reflink && functional_copy_file_range ()) | |
164 | @@ -362,6 +498,103 @@ | |
e79174a7 AM |
165 | |
166 | while (max_n_read) | |
167 | { | |
168 | + | |
b09470a3 | 169 | + /* BEGIN progress mod */ |
e79174a7 | 170 | + if (progress) { |
e79174a7 AM |
171 | + /* update countdown */ |
172 | + s_progress->iCountDown--; | |
173 | + char * sProgressBar = s_progress->cProgressField[5]; | |
174 | + if ( s_progress->iCountDown < 0 ) | |
175 | + s_progress->iCountDown = 100; | |
176 | + | |
177 | + /* just print one line with the percentage, but not always */ | |
178 | + if ( s_progress->iCountDown == 0 ) | |
179 | + { | |
180 | + /* calculate current speed */ | |
181 | + struct timeval cur_time; | |
182 | + gettimeofday ( & cur_time, NULL ); | |
183 | + int cur_size = g_iTotalWritten + *total_n_read / 1024; | |
b09470a3 | 184 | + int cur_fsize = g_iFTotalWritten + *total_n_read / 1024; |
e79174a7 AM |
185 | + int usec_elapsed = cur_time.tv_usec - s_progress->last_time.tv_usec; |
186 | + double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
187 | + sec_elapsed += ( double ) ( cur_time.tv_sec - s_progress->last_time.tv_sec ); | |
188 | + int copy_speed = ( int ) ( ( double ) ( cur_size - s_progress->last_size ) | |
189 | + / sec_elapsed ); | |
190 | + char s_copy_speed[20]; | |
191 | + file_size_format ( s_copy_speed, copy_speed >= 0 ? copy_speed : 0, 1 ); | |
192 | + /* update vars */ | |
193 | + s_progress->last_time = cur_time; | |
194 | + s_progress->last_size = cur_size; | |
195 | + | |
196 | + /* how many time has passed since the start? */ | |
197 | + int isec_elapsed = cur_time.tv_sec - g_oStartTime.tv_sec; | |
b09470a3 | 198 | + int isec_felapsed = cur_time.tv_sec - g_oFStartTime.tv_sec; |
e79174a7 AM |
199 | + int sec_remaining = ( int ) ( ( double ) isec_elapsed / cur_size |
200 | + * g_iTotalSize ) - isec_elapsed; | |
b09470a3 MK |
201 | + int sec_fremaining = ( int ) ( ( double ) isec_felapsed / cur_fsize |
202 | + * g_iFTotalSize ) - isec_felapsed; | |
e79174a7 | 203 | + /* print out */ |
b09470a3 MK |
204 | + |
205 | + char f_ttime[20]; | |
206 | + char f_ftime[20]; | |
207 | + format_time(f_ttime, sec_remaining, true); | |
208 | + format_time(f_ftime, sec_fremaining, true); | |
209 | + | |
210 | + sprintf ( s_progress->cProgressField[1], | |
211 | + move_mode | |
212 | + ? "%d of %d files moved (about %s remaining) " | |
213 | + : "%d of %d files copied (about %s remaining) ", | |
214 | + g_iFilesCopied, g_iTotalFiles, f_ttime ); | |
215 | + | |
216 | + char s_ftime[40] = ""; | |
217 | + | |
218 | + if (g_iTotalFiles > 1) | |
219 | + sprintf ( s_ftime, "(about %s remaining)", f_ftime ); | |
220 | + else | |
221 | + sprintf ( s_ftime, "(about %s remaining)", f_ttime ); | |
222 | + | |
e79174a7 AM |
223 | + sprintf ( s_progress->cProgressField[3], |
224 | + move_mode | |
b09470a3 MK |
225 | + ? "moving at %s/s %s" |
226 | + : "copying at %s/s %s", s_copy_speed, s_ftime ); | |
e79174a7 AM |
227 | + |
228 | + int fs_len; | |
229 | + if ( g_iTotalFiles > 1 ) | |
230 | + { | |
231 | + /* global progress bar */ | |
232 | + file_progress_bar ( s_progress->cProgressField[2], s_progress->iBarLength, | |
233 | + g_iTotalWritten + *total_n_read / 1024, g_iTotalSize ); | |
234 | + | |
235 | + /* print the global status */ | |
236 | + fs_len = file_size_format ( s_progress->cProgressField[1] + s_progress->iBarLength - 21, | |
237 | + g_iTotalWritten + *total_n_read / 1024, 1 ); | |
238 | + s_progress->cProgressField[1][s_progress->iBarLength - 21 + fs_len] = ' '; | |
239 | + } | |
240 | + | |
241 | + /* current progress bar */ | |
242 | + file_progress_bar ( sProgressBar, s_progress->iBarLength, *total_n_read, s_progress->src_open_sb.st_size ); | |
243 | + | |
244 | + /* print the status */ | |
245 | + fs_len = file_size_format ( s_progress->cProgressField[4] + s_progress->iBarLength - 21, *total_n_read, 0 ); | |
246 | + s_progress->cProgressField[4][s_progress->iBarLength - 21 + fs_len] = ' '; | |
247 | + | |
248 | + /* print the field */ | |
249 | + int it; | |
250 | + for ( it = g_iTotalFiles>1 ? 0 : 3; it < 6; it++ ) | |
251 | + { | |
252 | + printf ( "\033[K%s\n", s_progress->cProgressField[it] ); | |
253 | + if ( strlen ( s_progress->cProgressField[it] ) < s_progress->iBarLength ) | |
b09470a3 | 254 | + printf ( "%s", "" ); |
e79174a7 AM |
255 | + } |
256 | + if ( g_iTotalFiles > 1 ) | |
257 | + printf ( "\r\033[6A" ); | |
258 | + else | |
259 | + printf ( "\r\033[3A" ); | |
260 | + fflush ( stdout ); | |
261 | + } | |
e79174a7 | 262 | + } |
b09470a3 | 263 | + /* END progress mod */ |
e79174a7 AM |
264 | + |
265 | ssize_t n_read = read (src_fd, buf, MIN (max_n_read, buf_size)); | |
266 | if (n_read < 0) | |
267 | { | |
b09470a3 | 268 | @@ -446,6 +679,14 @@ |
e79174a7 AM |
269 | certain files in /proc or /sys with linux kernels. */ |
270 | } | |
271 | ||
272 | + /* BEGIN progress mod */ | |
273 | + if (progress) { | |
274 | + /* update total size */ | |
275 | + g_iTotalWritten += *total_n_read / 1024; | |
276 | + g_iFilesCopied++; | |
277 | + } | |
278 | + /* END progress mod */ | |
279 | + | |
280 | /* Ensure a trailing hole is created, so that subsequent | |
281 | calls of sparse_copy() start at the correct offset. */ | |
282 | if (make_hole && ! create_hole (dest_fd, dst_name, punch_holes, psize)) | |
b09470a3 | 283 | @@ -516,9 +757,11 @@ |
e79174a7 | 284 | static bool |
b09470a3 MK |
285 | lseek_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, |
286 | size_t hole_size, off_t ext_start, off_t src_total_size, | |
287 | - enum Sparse_type sparse_mode, | |
288 | + enum Sparse_type sparse_mode, bool move_mode, | |
289 | bool allow_reflink, | |
290 | - char const *src_name, char const *dst_name) | |
291 | + char const *src_name, char const *dst_name, | |
292 | + int iCountDown, char ** cProgressField, struct timeval last_time, | |
293 | + int last_size, int iBarLength, struct stat src_open_sb) | |
e79174a7 | 294 | { |
e79174a7 | 295 | off_t last_ext_start = 0; |
b09470a3 MK |
296 | off_t last_ext_len = 0; |
297 | @@ -590,10 +833,16 @@ | |
298 | is conservative and may miss some holes. */ | |
299 | off_t n_read; | |
300 | bool read_hole; | |
e79174a7 | 301 | + |
b09470a3 MK |
302 | + struct timeval a; |
303 | + struct stat b; | |
e79174a7 | 304 | + |
b09470a3 | 305 | + struct progress_status s_progress={iCountDown, cProgressField, last_time, last_size, iBarLength, src_open_sb}; |
e79174a7 | 306 | + |
b09470a3 MK |
307 | if ( ! sparse_copy (src_fd, dest_fd, buf, buf_size, |
308 | sparse_mode == SPARSE_NEVER ? 0 : hole_size, | |
309 | - true, allow_reflink, src_name, dst_name, | |
310 | - ext_len, &n_read, &read_hole)) | |
311 | + true, allow_reflink, move_mode, src_name, | |
312 | + dst_name, ext_len, &n_read, &read_hole, &s_progress)) | |
313 | return false; | |
e79174a7 | 314 | |
b09470a3 MK |
315 | dest_pos = ext_start + n_read; |
316 | @@ -1374,8 +1623,80 @@ | |
e79174a7 AM |
317 | buf_alloc = xmalloc (buf_size + buf_alignment); |
318 | buf = ptr_align (buf_alloc, buf_alignment); | |
319 | ||
320 | + /* BEGIN progress mod */ | |
321 | + /* create a field of 6 lines */ | |
322 | + char ** cProgressField = ( char ** ) calloc ( 6, sizeof ( char * ) ); | |
323 | + /* get console width */ | |
324 | + int iBarLength = 80; | |
325 | + struct winsize win; | |
326 | + if ( ioctl (STDOUT_FILENO, TIOCGWINSZ, (char *) &win) == 0 && win.ws_col > 0 ) | |
327 | + if (win.ws_col > iBarLength) /* String printed may be longer on smaller screens */ | |
328 | + iBarLength = win.ws_col; | |
329 | + /* create rows */ | |
330 | + int it; | |
331 | + for ( it = 0; it < 6; it++ ) | |
332 | + { | |
333 | + cProgressField[it] = ( char * ) malloc ( iBarLength + 1 ); | |
334 | + /* init with spaces */ | |
335 | + int j; | |
336 | + for ( j = 0; j < iBarLength; j++ ) | |
337 | + cProgressField[it][j] = ' '; | |
338 | + cProgressField[it][iBarLength] = '\0'; | |
339 | + } | |
340 | + | |
341 | + /* global progress bar? */ | |
342 | + if ( g_iTotalFiles > 1 ) | |
343 | + { | |
344 | + /* init global progress bar */ | |
345 | + cProgressField[2][0] = '['; | |
346 | + cProgressField[2][iBarLength - 8] = ']'; | |
347 | + cProgressField[2][iBarLength - 7] = ' '; | |
348 | + cProgressField[2][iBarLength - 1] = '%'; | |
349 | + | |
350 | + /* total size */ | |
351 | + cProgressField[1][iBarLength - 11] = '/'; | |
352 | + file_size_format ( cProgressField[1] + iBarLength - 9, g_iTotalSize, 1 ); | |
353 | + | |
354 | + /* show how many files were written */ | |
b09470a3 MK |
355 | + int sum_length = 0; |
356 | + sum_length = sprintf ( cProgressField[1], | |
357 | + x->move_mode | |
358 | + ? "%d of %d files moved so far" | |
359 | + : "%d of %d files copied so far", g_iFilesCopied, g_iTotalFiles ); | |
e79174a7 AM |
360 | + cProgressField[1][sum_length] = ' '; |
361 | + } | |
362 | + | |
363 | + /* truncate filename? */ | |
364 | + int fn_length; | |
365 | + if ( strlen ( src_name ) > iBarLength - 22 ) | |
366 | + fn_length = | |
367 | + sprintf ( cProgressField[4], "...%s", src_name + ( strlen ( src_name ) - iBarLength + 25 ) ); | |
368 | + else | |
369 | + fn_length = sprintf ( cProgressField[4], "%s", src_name ); | |
370 | + cProgressField[4][fn_length] = ' '; | |
371 | + | |
372 | + /* filesize */ | |
373 | + cProgressField[4][iBarLength - 11] = '/'; | |
374 | + file_size_format ( cProgressField[4] + iBarLength - 9, src_open_sb.st_size, 0 ); | |
375 | + | |
376 | + int iCountDown = 1; | |
377 | + char * sProgressBar = cProgressField[5]; | |
378 | + sProgressBar[0] = '['; | |
379 | + sProgressBar[iBarLength - 8] = ']'; | |
380 | + sProgressBar[iBarLength - 7] = ' '; | |
381 | + sProgressBar[iBarLength - 1] = '%'; | |
382 | + | |
383 | + /* this will always save the time in between */ | |
384 | + struct timeval last_time; | |
385 | + gettimeofday ( & last_time, NULL ); | |
386 | + int last_size = g_iTotalWritten; | |
387 | + /* END progress mod */ | |
388 | + | |
e79174a7 | 389 | off_t n_read; |
b09470a3 MK |
390 | bool wrote_hole_at_eof = false; |
391 | + | |
e79174a7 | 392 | + struct progress_status s_progress = { iCountDown, cProgressField, last_time, last_size, iBarLength, src_open_sb}; |
b09470a3 MK |
393 | + |
394 | if (! ( | |
395 | #ifdef SEEK_HOLE | |
396 | scantype == LSEEK_SCANTYPE | |
397 | @@ -1383,15 +1704,17 @@ | |
398 | scan_inference.ext_start, src_open_sb.st_size, | |
399 | make_holes ? x->sparse_mode : SPARSE_NEVER, | |
400 | x->reflink_mode != REFLINK_NEVER, | |
401 | - src_name, dst_name) | |
402 | + x->move_mode, src_name, dst_name, | |
403 | + iCountDown, cProgressField, last_time, last_size, | |
404 | + iBarLength, src_open_sb) | |
405 | : | |
406 | #endif | |
407 | sparse_copy (source_desc, dest_desc, buf, buf_size, | |
408 | make_holes ? hole_size : 0, | |
409 | x->sparse_mode == SPARSE_ALWAYS, | |
410 | x->reflink_mode != REFLINK_NEVER, | |
411 | - src_name, dst_name, UINTMAX_MAX, &n_read, | |
412 | - &wrote_hole_at_eof))) | |
413 | + x->move_mode, src_name, dst_name, UINTMAX_MAX, | |
414 | + &n_read, &wrote_hole_at_eof, &s_progress))) | |
e79174a7 AM |
415 | { |
416 | return_val = false; | |
417 | goto close_src_and_dst_desc; | |
b09470a3 | 418 | @@ -1402,6 +1725,14 @@ |
e79174a7 AM |
419 | return_val = false; |
420 | goto close_src_and_dst_desc; | |
421 | } | |
b09470a3 | 422 | + /* BEGIN progress mod */ |
e79174a7 AM |
423 | + if (progress) { |
424 | + int i; | |
425 | + for ( i = 0; i < 6; i++ ) | |
426 | + free ( cProgressField[i] ); | |
427 | + free ( cProgressField ); | |
428 | + } | |
429 | + /* END progress mod */ | |
430 | } | |
431 | ||
b09470a3 MK |
432 | if (x->preserve_timestamps) |
433 | diff -aur coreutils-9.0/src/copy.h coreutils-9.0-patched/src/copy.h | |
434 | --- coreutils-9.0/src/copy.h 2021-09-24 17:01:05.000000000 +0530 | |
435 | +++ coreutils-9.0-patched/src/copy.h 2022-03-27 05:54:15.844209471 +0530 | |
436 | @@ -236,6 +236,9 @@ | |
e79174a7 AM |
437 | Create destination directories as usual. */ |
438 | bool symbolic_link; | |
439 | ||
440 | + /* If true, draw a nice progress bar on screen */ | |
441 | + bool progress_bar; | |
442 | + | |
443 | /* If true, do not copy a nondirectory that has an existing destination | |
444 | with the same or newer modification time. */ | |
445 | bool update; | |
b09470a3 | 446 | @@ -308,4 +311,22 @@ |
e79174a7 AM |
447 | bool chown_failure_ok (struct cp_options const *) _GL_ATTRIBUTE_PURE; |
448 | mode_t cached_umask (void); | |
449 | ||
b09470a3 MK |
450 | +/* BEGIN progress mod */ |
451 | +FILE * spawn( const char *cmd, char *const argv[] ); | |
452 | +void format_time ( char * _cDst, double seconds, bool showall ); | |
453 | + | |
e79174a7 AM |
454 | +int file_size_format ( char * _cDst, long _lSize, int _iCounter ); |
455 | + | |
456 | +__attribute__((__common__)) long g_iTotalSize; | |
b09470a3 | 457 | +__attribute__((__common__)) long g_iFTotalSize; |
e79174a7 | 458 | +__attribute__((__common__)) long g_iTotalWritten; |
b09470a3 | 459 | +__attribute__((__common__)) long g_iFTotalWritten; |
e79174a7 | 460 | +__attribute__((__common__)) int g_iFilesCopied; |
b09470a3 | 461 | +__attribute__((__common__)) int g_iDirectoriesCopied; |
e79174a7 | 462 | +__attribute__((__common__)) struct timeval g_oStartTime; |
b09470a3 | 463 | +__attribute__((__common__)) struct timeval g_oFStartTime; |
e79174a7 AM |
464 | +__attribute__((__common__)) int g_iTotalFiles; |
465 | +__attribute__((__common__)) bool progress; | |
b09470a3 | 466 | +/* END progress mod */ |
e79174a7 AM |
467 | + |
468 | #endif | |
b09470a3 MK |
469 | diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c |
470 | --- coreutils-9.0/src/cp.c 2021-09-24 17:01:05.000000000 +0530 | |
471 | +++ coreutils-9.0-patched/src/cp.c 2022-03-27 06:28:53.896713403 +0530 | |
e79174a7 AM |
472 | @@ -131,6 +131,7 @@ |
473 | {"symbolic-link", no_argument, NULL, 's'}, | |
474 | {"target-directory", required_argument, NULL, 't'}, | |
475 | {"update", no_argument, NULL, 'u'}, | |
476 | + {"progress-bar", no_argument, NULL, 'g'}, | |
477 | {"verbose", no_argument, NULL, 'v'}, | |
478 | {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, | |
479 | {GETOPT_HELP_OPTION_DECL}, | |
b09470a3 | 480 | @@ -170,6 +171,9 @@ |
e79174a7 AM |
481 | -f, --force if an existing destination file cannot be\n\ |
482 | opened, remove it and try again (this option\n\ | |
483 | is ignored when the -n option is also used)\n\ | |
b09470a3 MK |
484 | + -g, --progress-bar add a progress bar.\n\ |
485 | + Note that this doesn't work with reflink,\n\ | |
486 | + reflink will be automatically disabled\n\ | |
e79174a7 AM |
487 | -i, --interactive prompt before overwrite (overrides a previous -n\ |
488 | \n\ | |
489 | option)\n\ | |
b09470a3 | 490 | @@ -634,6 +638,82 @@ |
e79174a7 AM |
491 | die (EXIT_FAILURE, 0, _("target %s is not a directory"), |
492 | quoteaf (file[n_files - 1])); | |
493 | } | |
b09470a3 | 494 | + /* BEGIN progress mod */ |
e79174a7 AM |
495 | + struct timeval start_time; |
496 | + if (progress) { | |
b09470a3 MK |
497 | + if (g_iTotalSize == 0) |
498 | + g_iTotalSize = 0; | |
499 | + if (g_iTotalFiles == 0) | |
500 | + g_iTotalFiles = n_files; | |
501 | + if (g_iFilesCopied == 0) | |
502 | + g_iFilesCopied = 0; | |
503 | + if (g_iDirectoriesCopied == 0) | |
504 | + g_iDirectoriesCopied = 0; | |
505 | + if (g_iTotalWritten == 0) | |
506 | + g_iTotalWritten = 0; | |
507 | + | |
508 | + if (target_directory_operand (file[0], &sb, &new_dst, forcing)) | |
509 | + g_iDirectoriesCopied++; | |
e79174a7 AM |
510 | + |
511 | + /* save time */ | |
512 | + gettimeofday ( & start_time, NULL ); | |
513 | + g_oStartTime = start_time; | |
514 | + | |
b09470a3 | 515 | + printf ( "calculating total size... \r" ); |
e79174a7 AM |
516 | + fflush ( stdout ); |
517 | + long iTotalSize = 0; | |
518 | + int iFiles = n_files; | |
519 | + if ( ! target_directory ) | |
520 | + iFiles = n_files - 1; | |
521 | + int j; | |
522 | + | |
523 | + /* how many files are we copying */ | |
e79174a7 AM |
524 | + FILE *fp ; |
525 | + char output[1024]; | |
b09470a3 MK |
526 | + fp = spawn("find", (char *[]){ "find", file[0], "-type", "f", NULL }); |
527 | + if ( fp == NULL) | |
528 | + printf("failed to run find\r"); | |
e79174a7 | 529 | + else |
b09470a3 MK |
530 | + { |
531 | + char *line_buf = NULL; | |
532 | + size_t line_buf_size = 0; | |
533 | + int line_count = 0; | |
534 | + ssize_t line_size; | |
535 | + line_size = getline(&line_buf, &line_buf_size, fp); | |
536 | + while (line_size > 0) | |
537 | + { | |
538 | + line_count++; | |
539 | + line_size = getline(&line_buf, &line_buf_size, fp); | |
540 | + } | |
541 | + free (line_buf); | |
542 | + if ( line_count > n_files ) | |
543 | + g_iTotalFiles = line_count; | |
544 | + } | |
e79174a7 AM |
545 | + |
546 | + for (j = 0; j < iFiles; j++) | |
547 | + { | |
548 | + /* call du -s for each file */ | |
b09470a3 | 549 | + fp = spawn("du", (char *[]){ "du", "-s", file[j], NULL }); |
e79174a7 | 550 | + if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { |
b09470a3 | 551 | + printf("failed to run du\r" ); |
e79174a7 AM |
552 | + } |
553 | + else | |
554 | + { | |
555 | + /* isolate size */ | |
556 | + strchr ( output, '\t' )[0] = '\0'; | |
557 | + iTotalSize += atol ( output ); | |
558 | + | |
b09470a3 | 559 | + printf ( "calculating total size... %ld\r", iTotalSize ); |
e79174a7 AM |
560 | + fflush ( stdout ); |
561 | + } | |
562 | + | |
563 | + /* close */ | |
564 | + pclose(fp); | |
565 | + } | |
b09470a3 | 566 | + g_iTotalSize += iTotalSize; |
e79174a7 | 567 | + } |
b09470a3 | 568 | + /* END progress mod */ |
e79174a7 AM |
569 | + |
570 | ||
571 | if (target_directory) | |
572 | { | |
b09470a3 | 573 | @@ -781,6 +861,56 @@ |
e79174a7 AM |
574 | ok = copy (source, new_dest, 0, x, &unused, NULL); |
575 | } | |
576 | ||
b09470a3 | 577 | + /* BEGIN progress mod */ |
e79174a7 | 578 | + if (progress) { |
e79174a7 AM |
579 | + /* remove everything */ |
580 | + int i; | |
581 | + if ( g_iTotalFiles > 1 ) | |
582 | + { | |
583 | + for ( i = 0; i < 6; i++ ) | |
584 | + printf ( "\033[K\n" ); | |
585 | + printf ( "\r\033[6A" ); | |
586 | + } | |
587 | + else | |
588 | + { | |
589 | + for ( i = 0; i < 3; i++ ) | |
590 | + printf ( "\033[K\n" ); | |
591 | + printf ( "\r\033[3A" ); | |
592 | + } | |
593 | + | |
594 | + /* save time */ | |
595 | + struct timeval end_time; | |
596 | + gettimeofday ( & end_time, NULL ); | |
597 | + int usec_elapsed = end_time.tv_usec - start_time.tv_usec; | |
598 | + double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
599 | + sec_elapsed += ( double ) ( end_time.tv_sec - start_time.tv_sec ); | |
600 | + | |
601 | + /* get total size */ | |
602 | + char sTotalWritten[20]; | |
603 | + file_size_format ( sTotalWritten, g_iTotalSize, 1 ); | |
604 | + /* TODO: using g_iTotalWritten would be more correct, but is less accurate */ | |
605 | + | |
606 | + /* calculate speed */ | |
607 | + int copy_speed = ( int ) ( ( double ) g_iTotalWritten / sec_elapsed ); | |
608 | + char s_copy_speed[20]; | |
609 | + file_size_format ( s_copy_speed, copy_speed, 1 ); | |
610 | + | |
611 | + /* good-bye message */ | |
b09470a3 MK |
612 | + char sFType[20]; |
613 | + if ( g_iDirectoriesCopied > 0 && g_iDirectoriesCopied == g_iFilesCopied ) | |
614 | + sprintf ( sFType, "%s", "folder(s)" ); | |
615 | + else if ( g_iDirectoriesCopied > 0 && g_iDirectoriesCopied < g_iFilesCopied ) | |
616 | + sprintf ( sFType, "%s", "folder(s)/file(s)" ); | |
617 | + else | |
618 | + sprintf ( sFType, "%s", "file(s)" ); | |
619 | + | |
620 | + char f_time[20]; | |
621 | + format_time(f_time, sec_elapsed, false); | |
622 | + printf ( "%d %s (%s) copied in %s (%s/s).\n", g_iFilesCopied, sFType, | |
623 | + sTotalWritten, f_time, s_copy_speed ); | |
e79174a7 | 624 | + } |
b09470a3 | 625 | + /* END progress mod */ |
e79174a7 AM |
626 | + |
627 | return ok; | |
628 | } | |
629 | ||
b09470a3 | 630 | @@ -816,6 +946,9 @@ |
e79174a7 AM |
631 | x->recursive = false; |
632 | x->sparse_mode = SPARSE_AUTO; | |
633 | x->symbolic_link = false; | |
b09470a3 | 634 | + |
e79174a7 | 635 | + x->progress_bar = false; |
b09470a3 | 636 | + |
e79174a7 AM |
637 | x->set_mode = false; |
638 | x->mode = 0; | |
639 | ||
b09470a3 | 640 | @@ -954,7 +1087,8 @@ |
e79174a7 AM |
641 | selinux_enabled = (0 < is_selinux_enabled ()); |
642 | cp_option_init (&x); | |
643 | ||
644 | - while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:TZ", | |
b09470a3 | 645 | + /* BEGIN and END progress mod - remove the g in the next line!*/ |
e79174a7 AM |
646 | + while ((c = getopt_long (argc, argv, "abdfgHilLnprst:uvxPRS:TZ", |
647 | long_opts, NULL)) | |
648 | != -1) | |
649 | { | |
b09470a3 | 650 | @@ -1011,6 +1145,10 @@ |
e79174a7 AM |
651 | x.unlink_dest_after_failed_open = true; |
652 | break; | |
653 | ||
654 | + case 'g': | |
655 | + progress = true; | |
656 | + break; | |
657 | + | |
658 | case 'H': | |
659 | x.dereference = DEREF_COMMAND_LINE_ARGUMENTS; | |
660 | break; | |
b09470a3 MK |
661 | @@ -1171,6 +1309,9 @@ |
662 | usage (EXIT_FAILURE); | |
663 | } | |
664 | ||
665 | + if (progress) | |
666 | + x.reflink_mode = REFLINK_NEVER; | |
667 | + | |
668 | x.backup_type = (make_backups | |
669 | ? xget_version (_("backup type"), | |
670 | version_control_string) | |
671 | diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c | |
672 | --- coreutils-9.0/src/mv.c 2021-09-24 17:01:05.000000000 +0530 | |
673 | +++ coreutils-9.0-patched/src/mv.c 2022-03-27 06:38:49.800838574 +0530 | |
e79174a7 AM |
674 | @@ -66,6 +66,7 @@ |
675 | {"target-directory", required_argument, NULL, 't'}, | |
676 | {"update", no_argument, NULL, 'u'}, | |
677 | {"verbose", no_argument, NULL, 'v'}, | |
b09470a3 | 678 | + {"progress-bar", no_argument, NULL, 'g'}, |
e79174a7 AM |
679 | {GETOPT_HELP_OPTION_DECL}, |
680 | {GETOPT_VERSION_OPTION_DECL}, | |
681 | {NULL, 0, NULL, 0} | |
b09470a3 | 682 | @@ -170,8 +171,128 @@ |
e79174a7 | 683 | { |
e79174a7 AM |
684 | bool copy_into_self; |
685 | bool rename_succeeded; | |
b09470a3 MK |
686 | + |
687 | + /* BEGIN progress mod */ | |
688 | + struct timeval start_time; | |
689 | + | |
690 | + if (progress && x->rename_errno != 0) { | |
691 | + if (g_iTotalSize == 0) | |
692 | + g_iTotalSize = 0; | |
693 | + if (g_iTotalFiles == 0) | |
694 | + g_iTotalFiles = 0; | |
695 | + if (g_iFilesCopied == 0) | |
696 | + g_iFilesCopied = 0; | |
697 | + if (g_iDirectoriesCopied == 0) | |
698 | + g_iDirectoriesCopied = 0; | |
699 | + if (g_iTotalWritten == 0) | |
700 | + g_iTotalWritten = 0; | |
701 | + | |
702 | + if (target_directory_operand (source)) | |
703 | + g_iDirectoriesCopied++; | |
e79174a7 AM |
704 | + |
705 | + gettimeofday (& start_time, NULL); | |
706 | + g_oStartTime = start_time; | |
707 | + | |
b09470a3 MK |
708 | + /* how many files are we copying */ |
709 | + FILE *fp ; | |
e79174a7 | 710 | + char output[1024]; |
b09470a3 MK |
711 | + fp = spawn("find", (char *[]){ "find", (char *)source, "-type", "f", NULL }); |
712 | + if ( fp == NULL) | |
713 | + printf("failed to run find\r"); | |
714 | + else | |
715 | + { | |
716 | + char *line_buf = NULL; | |
717 | + size_t line_buf_size = 0; | |
718 | + int line_count = 0; | |
719 | + ssize_t line_size; | |
720 | + line_size = getline(&line_buf, &line_buf_size, fp); | |
721 | + while (line_size > 0) | |
722 | + { | |
723 | + line_count++; | |
724 | + line_size = getline(&line_buf, &line_buf_size, fp); | |
725 | + } | |
726 | + free (line_buf); | |
727 | + g_iTotalFiles = line_count; | |
728 | + } | |
729 | + /* close */ | |
730 | + pclose(fp); | |
e79174a7 | 731 | + |
b09470a3 MK |
732 | + printf ("calculating total size... \r"); |
733 | + fflush (stdout); | |
734 | + long iTotalSize = 0; | |
735 | + /* call du -s for source */ | |
736 | + fp = spawn("du", (char *[]){ "du", "-s", (unsigned char *)(size_t)source, NULL }); | |
e79174a7 | 737 | + if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { |
b09470a3 | 738 | + printf("failed to run du\r" ); |
e79174a7 AM |
739 | + } |
740 | + else | |
741 | + { | |
742 | + /* isolate size */ | |
743 | + strchr ( output, '\t' )[0] = '\0'; | |
744 | + iTotalSize += atol ( output ); | |
b09470a3 | 745 | + printf ( "calculating total size... %ld\r", iTotalSize ); |
e79174a7 AM |
746 | + fflush ( stdout ); |
747 | + } | |
748 | + | |
749 | + /* close */ | |
750 | + pclose(fp); | |
b09470a3 | 751 | + g_iTotalSize += iTotalSize; |
e79174a7 | 752 | + } |
b09470a3 | 753 | + /* END progress mod */ |
e79174a7 AM |
754 | + |
755 | bool ok = copy (source, dest, false, x, ©_into_self, &rename_succeeded); | |
756 | ||
b09470a3 | 757 | + /* BEGIN progress mod */ |
e79174a7 | 758 | + if (progress && (x->rename_errno != 0 && ok)) { |
e79174a7 AM |
759 | + /* remove everything */ |
760 | + int i; | |
761 | + int limit = (g_iTotalFiles > 1 ? 6 : 3); | |
b09470a3 MK |
762 | + if (!rename_succeeded) |
763 | + { | |
764 | + for ( i = 0; i < limit; i++ ) | |
765 | + printf ( "\033[K\n" ); | |
766 | + printf ( "\r\033[3A" ); | |
767 | + } | |
e79174a7 AM |
768 | + |
769 | + /* save time */ | |
770 | + struct timeval end_time; | |
771 | + gettimeofday ( & end_time, NULL ); | |
772 | + int usec_elapsed = end_time.tv_usec - start_time.tv_usec; | |
773 | + double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
774 | + sec_elapsed += ( double ) ( end_time.tv_sec - start_time.tv_sec ); | |
775 | + | |
776 | + /* get total size */ | |
777 | + char sTotalWritten[20]; | |
778 | + file_size_format ( sTotalWritten, g_iTotalSize, 1 ); | |
779 | + /* TODO: using g_iTotalWritten would be more correct, but is less accurate */ | |
780 | + | |
781 | + /* calculate speed */ | |
782 | + int copy_speed = ( int ) ( ( double ) g_iTotalWritten / sec_elapsed ); | |
783 | + char s_copy_speed[20]; | |
784 | + file_size_format ( s_copy_speed, copy_speed, 1 ); | |
785 | + | |
b09470a3 MK |
786 | + /* increase counter */ |
787 | + g_iFilesCopied++; | |
788 | + | |
e79174a7 | 789 | + /* good-bye message */ |
b09470a3 MK |
790 | + if ( x->last_file ) |
791 | + { | |
792 | + char sFType[20]; | |
793 | + if ( g_iDirectoriesCopied > 0 && g_iDirectoriesCopied == g_iFilesCopied ) | |
794 | + sprintf ( sFType, "%s", "folder(s)" ); | |
795 | + else if ( g_iDirectoriesCopied > 0 && g_iDirectoriesCopied < g_iFilesCopied ) | |
796 | + sprintf ( sFType, "%s", "folder(s)/file(s)" ); | |
797 | + else | |
798 | + sprintf ( sFType, "%s", "file(s)" ); | |
799 | + | |
800 | + char f_time[20]; | |
801 | + format_time(f_time, sec_elapsed, false); | |
802 | + printf ( "%d %s (%s) moved in %s (%s/s).\n", g_iFilesCopied, sFType, | |
803 | + sTotalWritten, f_time, s_copy_speed ); | |
804 | + } | |
e79174a7 | 805 | + } |
b09470a3 | 806 | + /* END progress mod */ |
e79174a7 AM |
807 | + |
808 | if (ok) | |
809 | { | |
810 | char const *dir_to_remove; | |
b09470a3 | 811 | @@ -306,6 +427,7 @@ |
e79174a7 AM |
812 | \n\ |
813 | -b like --backup but does not accept an argument\n\ | |
814 | -f, --force do not prompt before overwriting\n\ | |
815 | + -g, --progress-bar add progress-bar\n\ | |
816 | -i, --interactive prompt before overwrite\n\ | |
817 | -n, --no-clobber do not overwrite an existing file\n\ | |
818 | If you specify more than one of -i, -f, -n, only the final one takes effect.\n\ | |
b09470a3 | 819 | @@ -361,7 +483,7 @@ |
e79174a7 AM |
820 | /* Try to disable the ability to unlink a directory. */ |
821 | priv_set_remove_linkdir (); | |
822 | ||
823 | - while ((c = getopt_long (argc, argv, "bfint:uvS:TZ", long_options, NULL)) | |
824 | + while ((c = getopt_long (argc, argv, "bfint:uvgS:TZ", long_options, NULL)) | |
825 | != -1) | |
826 | { | |
827 | switch (c) | |
b09470a3 | 828 | @@ -407,6 +529,9 @@ |
e79174a7 AM |
829 | case 'v': |
830 | x.verbose = true; | |
831 | break; | |
e79174a7 AM |
832 | + case 'g': |
833 | + progress = true; | |
834 | + break; | |
e79174a7 AM |
835 | case 'S': |
836 | make_backups = true; | |
837 | backup_suffix = optarg; |