Converts the given size in bytes in two possible ways: 1) target_unit is specified (!= 0): size is converted to target unit. 2) target_unit is not specified (== 0): size is converted to the first unit which will bring size to below 2048.
If specified, label will point to the long label ('MB') if long_labels is set or the short label ('M') if it is not. Additionally, ShowSize is no longer locked to MB but will scale units as required. Signed-off-by: Jakob Gruber <jakob.gru...@gmail.com> --- src/pacman/callback.c | 45 ++++++++------------------------- src/pacman/package.c | 18 +++++++------ src/pacman/query.c | 7 ++--- src/pacman/sync.c | 7 ++--- src/pacman/util.c | 65 ++++++++++++++++++++++++++++++++++++++---------- src/pacman/util.h | 1 + 6 files changed, 79 insertions(+), 64 deletions(-) diff --git a/src/pacman/callback.c b/src/pacman/callback.c index a80172b..769031a 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -491,10 +491,11 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) int totaldownload = 0; off_t xfered, total; - double rate = 0.0, timediff = 0.0, f_xfered = 0.0; + double rate = 0.0, timediff = 0.0; unsigned int eta_h = 0, eta_m = 0, eta_s = 0; + double rate_human, xfered_human; + const char *rate_label, *xfered_label; int file_percent = 0, total_percent = 0; - char rate_size = 'K', xfered_size = 'K'; if(config->noprogressbar || file_total == -1) { if(file_xfered == 0) { @@ -556,7 +557,7 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) diff_sec = current_time.tv_sec - initial_time.tv_sec; diff_usec = current_time.tv_usec - initial_time.tv_usec; timediff = diff_sec + (diff_usec / 1000000.0); - rate = xfered / (timediff * 1024.0); + rate = xfered / timediff; /* round elapsed time to the nearest second */ eta_s = (int)(timediff + 0.5); @@ -568,10 +569,10 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) /* return if the calling interval was too short */ return; } - rate = (xfered - xfered_last) / (timediff * 1024.0); + rate = (xfered - xfered_last) / timediff; /* average rate to reduce jumpiness */ rate = (rate + 2 * rate_last) / 3; - eta_s = (total - xfered) / (rate * 1024.0); + eta_s = (total - xfered) / rate; rate_last = rate; xfered_last = xfered; } @@ -625,37 +626,13 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) } - /* Awesome formatting for progress bar. We need a mess of Kb->Mb->Gb stuff - * here. We'll use limit of 2048 for each until we get some empirical */ - /* rate_size = 'K'; was set above */ - if(rate > 2048.0) { - rate /= 1024.0; - rate_size = 'M'; - if(rate > 2048.0) { - rate /= 1024.0; - rate_size = 'G'; - /* we should not go higher than this for a few years (9999.9 Gb/s?)*/ - } - } - - f_xfered = xfered / 1024.0; /* convert to K by default */ - /* xfered_size = 'K'; was set above */ - if(f_xfered > 2048.0) { - f_xfered /= 1024.0; - xfered_size = 'M'; - if(f_xfered > 2048.0) { - f_xfered /= 1024.0; - xfered_size = 'G'; - /* I should seriously hope that archlinux packages never break - * the 9999.9GB mark... we'd have more serious problems than the progress - * bar in pacman */ - } - } + rate_human = humanize_size((off_t)rate, 0, 0, &rate_label); + xfered_human = humanize_size(xfered, 0, 0, &xfered_label); /* 1 space + filenamelen + 1 space + 7 for size + 1 + 7 for rate + 2 for /s + 1 space + 8 for eta */ - printf(" %ls%-*s %6.1f%c %#6.1f%c/s %02u:%02u:%02u", wcfname, - padwid, "", f_xfered, xfered_size, - rate, rate_size, eta_h, eta_m, eta_s); + printf(" %ls%-*s %6.1f%s %#6.1f%s/s %02u:%02u:%02u", wcfname, + padwid, "", xfered_human, xfered_label, rate_human, rate_label, + eta_h, eta_m, eta_s); free(fname); free(wcfname); diff --git a/src/pacman/package.c b/src/pacman/package.c index 77a5ee7..39e36f6 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -51,6 +51,8 @@ void dump_pkg_full(pmpkg_t *pkg, int level) const char *reason; time_t bdate, idate; char bdatestr[50] = "", idatestr[50] = ""; + const char *label; + double size; const alpm_list_t *i; alpm_list_t *requiredby = NULL, *depstrings = NULL; @@ -105,17 +107,17 @@ void dump_pkg_full(pmpkg_t *pkg, int level) } list_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg)); list_display(_("Replaces :"), alpm_pkg_get_replaces(pkg)); + + size = humanize_size(alpm_pkg_get_size(pkg), 'K', 1, &label); if(level < 0) { - printf(_("Download Size : %6.2f K\n"), - (double)alpm_pkg_get_size(pkg) / 1024.0); - } - if(level == 0) { - printf(_("Compressed Size: %6.2f K\n"), - (double)alpm_pkg_get_size(pkg) / 1024.0); + printf(_("Download Size : %6.2f %s\n"), size, label); + } else if(level == 0) { + printf(_("Compressed Size: %6.2f %s\n"), size, label); } - printf(_("Installed Size : %6.2f K\n"), - (double)alpm_pkg_get_isize(pkg) / 1024.0); + size = humanize_size(alpm_pkg_get_isize(pkg), 'K', 1, &label); + printf(_("Installed Size : %6.2f %s\n"), size, label); + string_display(_("Packager :"), alpm_pkg_get_packager(pkg)); string_display(_("Architecture :"), alpm_pkg_get_arch(pkg)); string_display(_("Build Date :"), bdatestr); diff --git a/src/pacman/query.c b/src/pacman/query.c index 18c6992..d3a90ff 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -247,10 +247,9 @@ static int query_search(alpm_list_t *targets) /* print the package size with the output if ShowSize option set */ if(!config->quiet && config->showsize) { - /* Convert byte size to MB */ - double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - - printf(" [%.2f MB]", mbsize); + const char *label; + double size = humanize_size(alpm_pkg_get_size(pkg), 0, 1, &label); + printf(" [%.2f %s]", size, label); } diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 26f6f82..aadb9e5 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -349,10 +349,9 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) /* print the package size with the output if ShowSize option set */ if(!config->quiet && config->showsize) { - /* Convert byte size to MB */ - double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - - printf(" [%.2f MB]", mbsize); + const char *label; + double size = humanize_size(alpm_pkg_get_size(pkg), 0, 1, &label); + printf(" [%.2f %s]", size, label); } if (!config->quiet) { diff --git a/src/pacman/util.c b/src/pacman/util.c index c08ebb1..ba93963 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -502,9 +502,10 @@ void list_display_linebreak(const char *title, const alpm_list_t *list) void display_targets(const alpm_list_t *pkgs, int install) { char *str; + const char *label; + double size; const alpm_list_t *i; off_t isize = 0, dlsize = 0; - double mbisize = 0.0, mbdlsize = 0.0; alpm_list_t *targets = NULL; if(!pkgs) { @@ -522,10 +523,9 @@ void display_targets(const alpm_list_t *pkgs, int install) /* print the package size with the output if ShowSize option set */ if(config->showsize) { - double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - - pm_asprintf(&str, "%s-%s [%.2f MB]", alpm_pkg_get_name(pkg), - alpm_pkg_get_version(pkg), mbsize); + size = humanize_size(alpm_pkg_get_size(pkg), 0, 1, &label); + pm_asprintf(&str, "%s-%s [%.2f %s]", alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg), size, label); } else { pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); @@ -533,19 +533,17 @@ void display_targets(const alpm_list_t *pkgs, int install) targets = alpm_list_add(targets, str); } - /* Convert byte sizes to MB */ - mbdlsize = (double)dlsize / (1024.0 * 1024.0); - mbisize = (double)isize / (1024.0 * 1024.0); - if(install) { pm_asprintf(&str, _("Targets (%d):"), alpm_list_count(targets)); list_display(str, targets); free(str); printf("\n"); - printf(_("Total Download Size: %.2f MB\n"), mbdlsize); + size = humanize_size(dlsize, 'M', 1, &label); + printf(_("Total Download Size: %.2f %s\n"), size, label); if(!(config->flags & PM_TRANS_FLAG_DOWNLOADONLY)) { - printf(_("Total Installed Size: %.2f MB\n"), mbisize); + size = humanize_size(isize, 'M', 1, &label); + printf(_("Total Installed Size: %.2f %s\n"), size, label); } } else { pm_asprintf(&str, _("Remove (%d):"), alpm_list_count(targets)); @@ -553,7 +551,8 @@ void display_targets(const alpm_list_t *pkgs, int install) free(str); printf("\n"); - printf(_("Total Removed Size: %.2f MB\n"), mbisize); + size = humanize_size(isize, 'M', 1, &label); + printf(_("Total Removed Size: %.2f %s\n"), size, label); } FREELIST(targets); @@ -594,6 +593,45 @@ static char *pkg_get_location(pmpkg_t *pkg) } } +/** Converts sizes in bytes into human readable units. + * + * @param bytes the size in bytes + * @param target_unit if equal to one of the short unit labels ('B', 'K', ...) + * bytes is converted to target_unit; if equal to 0, the first + * unit which will bring the value to below a threshold of 2048 + * will be chosen. + * @param long_labels whether to use short ("K") or long ("KB") unit labels + * @param label will be set to the appropriate unit label + * + * @return the size in the appropriate unit + */ +double humanize_size(off_t bytes, const char target_unit, int long_labels, + const char **label) +{ + static const char *shortlabels[] = {"B", "K", "M", "G", "T", "P"}; + static const char *longlabels[] = {"B", "KB", "MB", "GB", "TB", "PB"}; + static const int unitcount = sizeof(shortlabels) / sizeof(shortlabels[0]); + + const char **labels = long_labels ? longlabels : shortlabels; + double val = (double)bytes; + int index; + + for(index = 0; index < unitcount - 1; index++) { + if(target_unit != 0 && shortlabels[index][0] == target_unit) { + break; + } else if(target_unit == 0 && val <= 2048.0) { + break; + } + val /= 1024.0; + } + + if(label) { + *label = labels[index]; + } + + return(val); +} + void print_packages(const alpm_list_t *packages) { const alpm_list_t *i; @@ -638,8 +676,7 @@ void print_packages(const alpm_list_t *packages) /* %s : size */ if(strstr(temp,"%s")) { char *size; - double mbsize = (double)pkg_get_size(pkg) / (1024.0 * 1024.0); - pm_asprintf(&size, "%.2f", mbsize); + pm_asprintf(&size, "%.2f", humanize_size(pkg_get_size(pkg), 'M', 0, NULL)); string = strreplace(temp, "%s", size); free(size); free(temp); diff --git a/src/pacman/util.h b/src/pacman/util.h index 234a631..6a20ba4 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -52,6 +52,7 @@ char *strtrim(char *str); char *strreplace(const char *str, const char *needle, const char *replace); alpm_list_t *strsplit(const char *str, const char splitchar); void string_display(const char *title, const char *string); +double humanize_size(off_t bytes, const char target_unit, int long_labels, const char **label); void list_display(const char *title, const alpm_list_t *list); void list_display_linebreak(const char *title, const alpm_list_t *list); void display_targets(const alpm_list_t *pkgs, int install); -- 1.7.4.1