#include static double gettime(void) { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec + (double)tv.tv_usec / 1000000.0; } static const char * format_eta(double remaining) { static char result[6] = ""; int seconds = remaining + 0.5; if(seconds >= 0 && seconds < 6000) { snprintf(result, sizeof(result), "%02d:%02d", seconds / 60, seconds % 60); return result; } return "--:--"; } static char * ssize(char * buf, double size) { const char * unit[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; int count = 0; while((size > 1024) && (count < 8)) { size /= 1024; count++; } sprintf(buf, "%5.3f %s", size, unit[count]); return buf; } void progress_start(struct progress_t * p, uint64_t total) { if(p && (total > 0)) { p->total = total; p->done = 0; p->start = gettime(); } } void progress_update(struct progress_t * p, uint64_t bytes) { char buf1[32], buf2[32]; if(p) { p->done += bytes; double ratio = p->total > 0 ? (double)p->done / (double)p->total : 0.0; double speed = (double)p->done / (gettime() - p->start); double eta = speed > 0 ? (p->total - p->done) / speed : 0; int i, pos = 48 * ratio; printf("\r%3.0f%% [", ratio * 100); for(i = 0; i < pos; i++) putchar('='); for(i = pos; i < 48; i++) putchar(' '); if(p->done < p->total) printf("] %s/s, ETA %s \r", ssize(buf1, speed), format_eta(eta)); else printf("] %s, %s/s \r", ssize(buf1, p->done), ssize(buf2, speed)); fflush(stdout); } } void progress_stop(struct progress_t * p) { if(p) printf("\r\n"); }