+ if (copy_debug.sparse_detection == COPY_DEBUG_UNKNOWN)
+ copy_debug.sparse_detection = hole_size ? COPY_DEBUG_YES : COPY_DEBUG_NO;
+ else if (hole_size && copy_debug.sparse_detection == COPY_DEBUG_EXTERNAL)
+@@ -339,6 +475,102 @@
+ (SSIZE_MAX, SIZE_MAX) truncated to a value that is
+ surely aligned well. */
+ ssize_t copy_max = MIN (SSIZE_MAX, SIZE_MAX) >> 30 << 30;
++
++ /* BEGIN progress mod */
++ if (progress) {
++ /* update countdown */
++ s_progress->iCountDown--;
++ char * sProgressBar = s_progress->cProgressField[5];
++ if ( s_progress->iCountDown < 0 )
++ s_progress->iCountDown = 100;
++
++ /* just print one line with the percentage, but not always */
++ if ( s_progress->iCountDown == 0 )
++ {
++ /* calculate current speed */
++ struct timeval cur_time;
++ gettimeofday ( & cur_time, NULL );
++ int cur_size = g_iTotalWritten + *total_n_read / 1024;
++ int cur_fsize = g_iFTotalWritten + *total_n_read / 1024;
++ int usec_elapsed = cur_time.tv_usec - s_progress->last_time.tv_usec;
++ double sec_elapsed = ( double ) usec_elapsed / 1000000.f;
++ sec_elapsed += ( double ) ( cur_time.tv_sec - s_progress->last_time.tv_sec );
++ int copy_speed = ( int ) ( ( double ) ( cur_size - s_progress->last_size )
++ / sec_elapsed );
++ char s_copy_speed[20];
++ file_size_format ( s_copy_speed, copy_speed >= 0 ? copy_speed : 0, 1 );
++ /* update vars */
++ s_progress->last_time = cur_time;
++ s_progress->last_size = cur_size;
++
++ /* how many time has passed since the start? */
++ int isec_elapsed = cur_time.tv_sec - g_oStartTime.tv_sec;
++ int isec_felapsed = cur_time.tv_sec - g_oFStartTime.tv_sec;
++ int sec_remaining = ( int ) ( ( double ) isec_elapsed / cur_size
++ * g_iTotalSize ) - isec_elapsed;
++ int sec_fremaining = ( int ) ( ( double ) isec_felapsed / cur_fsize
++ * g_iFTotalSize ) - isec_felapsed;
++ /* print out */
++
++ char f_ttime[20];
++ char f_ftime[20];
++ format_time(f_ttime, sec_remaining, true);
++ format_time(f_ftime, sec_fremaining, true);
++
++ int fs_len;
++ fs_len = sprintf ( s_progress->cProgressField[1],
++ move_mode
++ ? "%d of %d files moved (about %s remaining)"
++ : "%d of %d files copied (about %s remaining)",
++ g_iFilesCopied, g_iTotalFiles, f_ttime );
++ s_progress->cProgressField[1][fs_len] = ' ';
++
++ char s_ftime[40] = "";
++
++ if (g_iTotalFiles > 1)
++ sprintf ( s_ftime, "(about %s remaining)", f_ftime );
++ else
++ sprintf ( s_ftime, "(about %s remaining)", f_ttime );
++
++ if ( g_iTotalFiles > 1 )
++ {
++ /* global progress bar */
++ file_progress_bar ( s_progress->cProgressField[2], s_progress->iBarLength,
++ g_iTotalWritten + *total_n_read / 1024, g_iTotalSize );
++
++ /* print the global status */
++ fs_len = file_size_format ( s_progress->cProgressField[1] + s_progress->iBarLength - 21,
++ g_iTotalWritten + *total_n_read / 1024, 1 );
++ s_progress->cProgressField[1][s_progress->iBarLength - 21 + fs_len] = ' ';
++ }
++
++ /* set current progress bar to be always 100 % */
++ file_progress_bar ( sProgressBar, s_progress->iBarLength, s_progress->src_open_sb.st_size, s_progress->src_open_sb.st_size );
++ s_progress->cProgressField[5][s_progress->iBarLength-2] = '0';
++ s_progress->cProgressField[5][s_progress->iBarLength-1] = '%';
++ s_progress->cProgressField[5][s_progress->iBarLength] = '\0';
++
++ /* print the status as always full filesize*/
++ fs_len = file_size_format ( s_progress->cProgressField[4] + s_progress->iBarLength - 21, s_progress->src_open_sb.st_size, 0 );
++ s_progress->cProgressField[4][s_progress->iBarLength - 21 + fs_len] = ' ';
++
++ /* print the field */
++ int it;
++ for ( it = g_iTotalFiles>1 ? 0 : 3; it < 6; it++ )
++ {
++ printf ( "\033[K%s\n", s_progress->cProgressField[it] );
++ if ( strlen ( s_progress->cProgressField[it] ) < s_progress->iBarLength )
++ printf ( "%s", "" );
++ }
++ if ( g_iTotalFiles > 1 )
++ printf ( "\r\033[6A" );
++ else
++ printf ( "\r\033[3A" );
++ fflush ( stdout );
++ }
++ }
++ /* END progress mod */
++
+ ssize_t n_copied = copy_file_range (src_fd, nullptr, dest_fd, nullptr,
+ MIN (max_n_read, copy_max), 0);
+ if (n_copied == 0)
+@@ -382,6 +614,14 @@
+ copy_debug.offload = COPY_DEBUG_YES;
+ max_n_read -= n_copied;
+ *total_n_read += n_copied;
++
++ /* BEGIN progress mod */
++ if (progress) {
++ /* update total size */
++ g_iTotalWritten += *total_n_read / 1024;
++ g_iFilesCopied++;
++ }
++ /* END progress mod */
+ }
+ else
+ copy_debug.offload = COPY_DEBUG_AVOIDED;
+@@ -392,6 +632,103 @@